/*  WEALTH1_couples_2019v3.C

-TO DO: switch to MRS for bequests (conditional on consumption) max(MRSimplied,0). Think about taxation of medicaid implication
-V1 (2022) Rory updated to decompose spousal risk
-V3(19) Rory updated the read in for the medex coefficients with new dummies - NOTE: I only have to update the read in because the switch to singles matrix auto applies this to the lag in the widow/widower case
	-  and it doesn't enter death costs (except through base singles matrix)
-V2(19) John fixed the scaling of disregards for couples
-V1 (19) Changed the read in for the bequest shifter to account correctly for 1 year 2 year change in GAUSS, incorporated disregards for medically needy pathway medicaid
-No disregards for final member death
- V6 (18) Fixed bug in locate. Updated an error in medicaid calculation in sim (level not eligibility). Fixed bug in computation of death costs and read in health variance shares.
Updated an error with integration over RoR in E[U(Bequest)] 08/19/18
- V5 (18) Updated timing in line with revision to model equations. Updated 06/03/18
- V4 (18) John adjusted calculation of medicaid to avoid double counting. Rory bottom coded interest payments when there are medical expenditures.
- V3 (18) Updated TAX SYSTEM PARAMETERS
-V2 (18) adjusted HCost switch to eliminate death expenses
-V1 (18) adjusted the computation of the precomputed bequest excpectation so that they  have a smaller memory footprint.
-V16 Fixed paths and an errant if statemkent that assigned 0 bequest to couples who die
-V15 Deallocated memory to prevent memory leaks. Fixed incorrect  index in getvaluesingle and added OpenMP compatibility. Double income and medcosts in CoH. Fixed incorrect calculation of medicaid
-V14. Updated sex indexing for simulation in line with GAUSS where erros. Added buffer flushes to print to command
line when using MPI. Updated MPI code for previously changed arrays- now with correct indexex etc.
Fixed a simulation error when storing death costs
-V13. adds the initital distribution matrix and renames medexsim as oopmedexsim.fmt
-Incorporates initial coh constructed from 1996 assets and 1996 gross incomes

- Solves model in De Nardi, French, Jones and McGee (2017), with both singles and couples
- New version revised by Rory McGee (09/2017). Changes flagged as *?#?* for easy tracking
- Major change to timing convention and medical costs
- Updated budget constraints for couples and singles and timing of choices for couples
- added test features
-eliminated bequest monotonicity
-incorporated difference between health status gauss indexing and C indexing
-Updated simulation code
-Incorporated lagged health status in medical expenditure
-This requires a deathcost matrices to deal with death costs, a lagged health status matrix which deals with widow lagged health
for surviving spouse & finally we pre-integrate the medical expenses and death costs for bequests when every member of the household dies
which gives us a larger single bequest utility matrix. Note to self: an alternative is to have singles transitions to matrices, but this seems as (if not more) involved

- New version revised by Rory McGee (03/2017). Changes flagged as *?#?* for easy tracking
- Reverted change to medcostshifter
- Added omega to preferences and to the value function continuation values for when one spouse dies.
- Fixed grid errors (singles for couples and vice versa), missing declerations, initialisations
and case-sensitivity typos
- Allowed for differential tax treatment of couples
- Corrected Age gaps, lifespans, model length,number of health states and logic checks
- New list of input files to incorporate couples data
- Correctly calculate bequests and bequest policy for couples
- Completed Simulation Code
- Cosmetic edits
- Changed om MPI code to auto comment and uncomment use precompilation macro
- New version revised by Mariacristina De Nardi (2014), including adding edits
by JBJ (July 08) to simulate discrete-valued transitory shocks.
- Old version written by Fang Yang, with Mariacristina De Nardi 10/06
(cosmetic edits by John Jones 1/07, 7/07)
- GAUSS-C I/O procedures written by K. Housinger (2003)

- I/O instructions
~ Put the (GAUSS) *.fmt files in a subdirectory called \iofiles\
~ create a folder called \data
~ create a folder called \output

-MPI INSTRUCTIONS
~ To use MPI two changes need to be made:
~ 1) #define MPI_COMMENT 0 changed to #define MPI_COMMENT 1 on line 107
~ 2)  #define useMPI 0 changed to 2 on line 127
~Finally to use on a PC rather than network, make sure data is stored on C drive

-OpenMP INSTRUCTIONS
~ To use OpenMP two changes need to be made:
~ 1) #define MPI_COMMENT 0 changed to #define MPI_COMMENT 2 on line 107
~ 2)  #define NUM_THREADS to the appropriagte thread number on line 125

-We use conditional compile to handle switching between MPI and OpenMP.
- This version switches to a two-year period to be consistent with the data frequency and to save
computation time. It also adopts a three state health status: good, bad, nursing home.

- Different grids for singles and couples due to different cMin (consumption floor).
However, I think that they have to have the same maximum, because when they switch
from couple to singles, they might be otherwise forced to leave bequests.

- Eliminated estate taxation.

- We need to check if the difference in indexes exists also for singles (as it did for couples)
Note the different indexes for males and females for couples: for a male age t=1,
means age=70,  for a female t=1 means age=67.
Both live up to age 100 (t=31 for males and 34 for females).

- There are four major subroutines.

~ GetRulesSingle does the maximization for the single cases.
~ GetValueSingle calculates value fn for each consumption choice and is used by GetRulesSingle.
~ GetRulesCouples does the maximization for the couple cases.
~ GetValueCouples calculates value fn for each consumption choice and is used by GetRulesCouples

- MDN (04/2014) Imported the following modifications introduced by John Johnes in 2008 in the singles
version of the code
-------------------------------------------------------------------------------------
- Medical expense shocks are discretized, both in the model and in the simulations.
- Modified by JBJ in July 08 to simulate discrete-valued transitory shocks.
Lots of new output matrices created and saved
New naming convention:
~ *cdfsim => simulations of U[0,1] draws
~ *indexim => simulations of index numbers
~ *sim => actual values
-------------------------------------------------------------------------------------
- Future modifications:
~ Solve policy function at T separately. This could save some time.
*/

#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <limits.h>

//  MPI-specific Code:  Uncomment if used in UNIX 
//IMPORTANT ::::: *?#?*- Added control sequence RM 03/17
//The following define statement now automates all uncommenting using preprocessor commands
//Change MPI_COMMENT TO 1 to inclue commands associated with MPI
#define MPI_COMMENT 2


//Begin the automated commenting *?#?*- Added control sequence RM 03/17
//Precompilation if statements will only include the enclosed code for compilation when MPI_comment==1
//Visual studio will grey this out as a visual cue, but still display syntax highlighting
#if(MPI_COMMENT==1)

#include <mpi.h>
#define max(x,y) ((x) > (y) ? (x) : (y))
#define min(x,y) ((x) < (y) ? (x) : (y))
#elif(MPI_COMMENT==2) //added RM *?#?* 11/17
#include <omp.h>
#endif(MPI_COMMENT==1)


// Disable warning messages 4996 
#pragma warning( once : 4996 )

#define NUM_THREADS 72  // PC has 8 threads, but save a thread for other work
#define switchJohn 3     // 0: Cristina, 1: John, 2: Rory on LARSHANSEN 3: Rory on NewPC
#define useMPI 0         // 0 => PC, 1 => Unix, 2 => cluster  
#define PI 3.14159265
#define rounder 0.0001
#define ABS_TOL 1e-08  // *?#?*- Added to avoid problems associated with logic checks for floating point and precision RM 06/17
#define ADDRESS_LEN 90

#define TESTCHECKS 0 // *?#?*  Added by RM 06/17
#define INCDEAD 0 // *?#?*  Added by RM 05/18 -- if 0 we do not include the dead household income in final bequest. If 1 we do.
#define TAXINCDEAD 0 // *?#?*  Added by RM 06/18 -- if 0 we do not tax household asset and pension income in final bequest. If 1 we do.

// These constants are used to size various matrices  
#define TDIMS 17       // dim. of age for single Programmer must ensure compatibility */
#define TDIMC 17       // dim. of age for couple, set to 1 when switchCouple = 0 Programmer must ensure compatibility */
#define IDIM 9         // dim. of permanent income, from lowest to highest 
#define HSDIM 3        // dim. of health status: good, bad, nursing home 
#define RDIM 1         // dim. of interest rate *** Do we want to deal with the rate of return shocks ? */
#define ZETADIM 6     // dim. of persistent component of health shock 
#define XIDIM 5        // dim. of temporary component of health shock 

//  GRIDS allowed to be different for consumption and assets in terms of minimum and grid points, 
//  but not maximum.
/*  CASHMAX is the upper bound of both assets and consumption. If not, forced bequests exists in some cases.
There would also be a complication when a couple member switches to single.
The lower bound  is different due to the consumption floor.
*/
#define CASHMAX    3000000.0 // max value for cash on hand and cons. 
#define CASHDIM    144              // number of points on the cash on hand last -144
#define CONSUMDIM  216              // number of points on the cash on hand grid -216
// other stuff
#define LAMBDAcashS 3.0                // nonlinearity of coh grid for singles
#define LAMBDAcashC 2.0                // nonlinearity of coh grid for couples
#define LAMBDAconsS 3.0                // nonlinearity of consumption grid for singles
#define LAMBDAconsC 2.0                // nonlinearity of consumption grid for couples
#define BEQUESTDIM 101                 // couples: dim. of bequests to other heirs
//#define taxDim 7                     // dim. of vector of marginal tax rates 

#define BASIC_HEADER_LEN 128 // Length of a scalar header 
#define BYTE_POS 5           // Int offset in header of byte order 
#define BIT_POS 6            // Int offset in header of bit order 
#define TYPE_POS 15          // Int offset in header of matrix type 
#define HEADER_LEN_POS 18    // Int offset in header of header length 
#define M_POS 32             // Int offset in header of value for m 
#define N_POS 33             // Int offset in header of value for n 
#define SCALAR 0             // Value of type that indicates a scalar 
#define MATRIX 2             // Value of type that indicates a matrix 
#define BIT_SYSTEM 0         // Value of bit order (0=backwards/i386) 
#define BYTE_SYSTEM 0        // Value of byte order (0=backwards/i386) 

//For passing the coefficients to generate profiles
#define COEFFNUM 18        //number of variables in demographic transition equation 12

#define GOODHEALTH 2 //The index for the goodhealth, this is necessary and now hardcoded when we calculate shifters for death etc. (which include an exlcuded category of present good health)
/*
**This is my GMatrix opaque datatype.  The gauss fmt format has implied
**dimensionality, but is just a list of doubles.  I could rewrite the
**functions to use pointers-to-pointers to improve the interface with
**Eric's functions, but that would add to the complexity of my code.  I
**suggest writing an intermediate function that turns *data into **data
**to cope with 2-dimensional arrays.
*/

typedef struct {   // this defines a matrix with given # of rows and 
	unsigned int m;  // columns and gives the address of the first element 
	unsigned int n;
	double* data;
} GMatrix;

//--------------------------------------------------------------------------------
//----------------------Global PARAMETERS read in from GAUSS----------------------

// Preference Parameters 
// delta=health pref. shifter. Now Dimension HDIM. delta[GH]=0
// beta=discount factor
// eta=economies of scales for couples
// nu=degree of risk aversion
// omega= weight on surviving spouses's continuation value ***
// rest: utility from bequests (0=single, 1=one surviving spouse, 2=both dead together)
double delta[HSDIM]; //*?#?*- Added delta array RM 06/17
double beta, eta, nu, omega, phi0, phi1, phi2, k0, k1, k2;

// Simulation Parameters 
int nsims, TDimSims, TSTART, MODELPERIOD;

// Switches 
int switchMor;    // 0: no shocks, 1: shocks of mortality risk 
int switchBeta;   // 0: from GAUSS, 1: beta=1 
int switchY;      // 0: noIncome 1: use income loaded 
int switchHCost;  // 0: no deterministic health cost, 1:  Health cost 
int switchTax;    // 0: no tax, 1: use tax  loaded  
int switchZeta;   // 0: no shocks, 1: shocks of health costs zeta,
int switchXi;     // 0: no shocks, 1: shocks of health costs zi 
int switchR;      // 0: no shocks, 1: shocks of interest rate,   
int switchBeq;    // 0: no, 1: bequest motive  
int switchGender; // 0: no, 1: gender diff 
int switchCouple; // 0: only solve single case, 1: single+couple  
int switchHouse;  /* 0: housing not excluded from Medicaid asset test, 1: exluded for non-institutionalized, 2: excluded for all */  //JBJ 03/08/12
int switchRisk; //0: no risk for singles(loads alternative medex profiles) 1: standard solution to the model, RM 10/21/22 - used to decomoppse risk for the surviving spouse ONLY 
int switchContrisk; //0: no risk for singles(loads alternative medex profiles) 1: standard solution to the model, RM 10/21/22 - used to decomoppse risk for the surviving spouse ONLY 
																																	 // Stuff related to setting the survival probabilities for experiments.  JBJ:  06/24/14 --Carried from AER paper RM 06.2017

int rank;   // Index number of this node  
int size;   //  Number of nodes in cluster 

			// Miscellaneous 
			// Cmin is the minimum consumption floor for singles and couples *****
double cMinS, cMinC, mu_r, sigma_r, medex_bottomcode, SSI_IncS, SSI_IncC, AssetDisregardS, AssetDisregardC, IncDisregardS, IncDisregardC, eta_FPL; // RM: 1/16/19, JBJ: 06/04/19
int WIFEAGEDIF; //The difference in ages between spouses in model periods

				/* Non-asset income:  y_(t)  =  y(f,IDIM,TDIMS+1), a deterministic fn.
				INDEXES:
				f: family structure
				f=0 single male
				f=1 single female
				f=2 both household members -is in seperate couples matrix
				IDIM: permanent income quantile, ordered from the lowest to highest
				TDIMS: age, where +1 is just a place holder
				*/
double ySM[2][IDIM][TDIMS + 1];  // *** Note TDIMS here, even though couples are included
								 ///** It would likely be better to have two separate matrices for singles and couples.
double yCM[IDIM][TDIMC + 1];  // *** Note TDIMC here

							  /* Health status at time t
							  INDEXES for singles and couples:
							  SEX: 0=male (h), 1=woman (w)
							  HSDIM: health state today
							  HSDIM: health state tomorrow
							  */
double hsProbSM[2][TDIMS][IDIM][HSDIM][HSDIM];  // Singles 
double hsProbCM[2][TDIMC][IDIM][HSDIM][HSDIM];  // Couples

												/* Survival uncertainty for singles and couples:
												s_(m, I, t)(i) denotes the probability of an individual i being alive at age t
												conditional on current health status, permanent income, and being alive at age t-1.
												0=male, 1=female, different for couples and singles
												*/
double survivalProbSM[2][TDIMS][HSDIM][IDIM];
double survivalProbCM[2][TDIMC][HSDIM][IDIM];

/* Health Costs
ln hc_(t)  =  hc(f_(t), m_(I,t)(h), m_(I,t)(w), t, I)+
sigma(f_(t), m_(I,t)(h), m_(I,t)(w), t, I) * psi_(t).
psi_(t)    =  zeta_(t)+xi_(t),   xi_(t) ~ N(0, sigma_(xi)^2),
zeta_(t)   =  rho_(hc)zeta_(t-1) + epsilon_(t),   epsilon_(t) ~ N(0, sigma_(epsilon)^2)
*/
double rhoHc, sigma_xi, sigma_zeta, sigma_epsilon;

// health cost functions 
// Singles lagged (current) current (next period) health, brackets from the perspective of the integration
double hcSIntercept[2][HSDIM][HSDIM][TDIMS + 1][IDIM];
// *** different name in John's version of the code
// *?#?* Updated RM 09/17 to allow for dependence on lagged health old version: double hcSIntercept[2][HSDIM][TDIMS + 1][IDIM];


// where it is double hcSingleLogMean[2][HSDIM][TDIMS+1][IDIM];
double hcSSigma[2][HSDIM][HSDIM][TDIMS + 1][IDIM];
//  *?#?* Updated RM 09/17 to allow for dependence on lagged health double hcSSigma[2][HSDIM][TDIMS + 1][IDIM];

// Couples [HSDIM][HSDIM][HSDIM][HSDIM] is [hsHIndLag][hsWIndLag]hsHInd][hsWInd] or [hsHInd][hsWInd]hsHIndN][hsWIndN] when taking expectations 
double hcCIntercept[HSDIM][HSDIM][HSDIM][HSDIM][TDIMC + 1][IDIM];
double hcCSigma[HSDIM][HSDIM][HSDIM][HSDIM][TDIMC + 1][IDIM];
/* *?#?* Updated RM 09/17 to allow for dependence on lagged health
double hcCIntercept[HSDIM][HSDIM][TDIMC + 1][IDIM];
double hcCSigma[HSDIM][HSDIM][TDIMC + 1][IDIM];*/


//death costs *?#?* added 08/17 RM & lag health added 09/17
double deathcostsIntercept[2][IDIM];
double deathcostsVar[2][IDIM]; //Remember these are variance coefficients! Requires some extra squaring and square rooting
							   //death costs *?#?* added for final member of the household 08/17 RM
double deathcostsFinalMemberC[TDIMC + 1][IDIM][HSDIM][HSDIM][ZETADIM][XIDIM];
double deathcostsFinalMemberS[2][TDIMS + 1][IDIM][HSDIM][ZETADIM][XIDIM];

/* This is going to duplicate code (or more speciffically the coefficients on lagged health), it is only used in the couples code
when we take an expectation and a widow(er) is left behind. There we use the medex matrices for the single when we calculate the
contination, to correctly calculate the medical expenses we pull the the dummy for the lagged health of the dead  */
double laghealthIntercept[2][HSDIM];
double laghealthVar[2][HSDIM]; //Remember these are variance coefficients! Requires some extra squaring and square rooting


							   /* Income tax structure, from Gouveia and Strauss, Guner et al estimates
							   b gives the proportionality (or maximum effective tax rate)
							   p gives progressivity
							   s gives size of sacrifice
							   *?#?* Updated RM 09/17to update the coefficients to version in Guner, Kaygusuz and Ventura 2014 RED (replaces 2012 WP) */
							   //For couples:
double   tax_p0 = 1.842;
double  tax_b0 = 0.227;
double tax_s0 = 0.001;
//For singles:
double  tax_p1 = 1.192;
double tax_b1 = 0.226;
double tax_s1 = 0.019;

/* Income tax structure, from French's code
taxBrk gives tax brackets
taxMar gives marginal tax rates

// *?#?* Differential treatment of singles and couples RM 01/2017
//For singles
double taxBrkS[taxDim-1] = {6250, 40200, 68400, 93950, 148250, 284700};
double taxMarS[taxDim] = {0.0765, 0.2616, 0.4119, 0.3499, 0.3834, 0.4360, 0.4761};
//For couples
double taxBrkC[taxDim-1] = {6250, 40200, 68400, 93950, 148250, 284700};
double taxMarC[taxDim] = {0.0765, 0.2616, 0.4119, 0.3499, 0.3834, 0.4360, 0.4761};
*/
/* OLD 2014 version:
double taxBrk[taxDim-1] = {6250, 40200, 68400, 93950, 148250, 284700};
double taxMar[taxDim] = {0.0765, 0.2616, 0.4119, 0.3499, 0.3834, 0.4360, 0.4761}; */

// Strings of directory names 
char rootdir[ADDRESS_LEN];
char outputdir[ADDRESS_LEN];
char datadir[ADDRESS_LEN];

//----------------Global VARIABLES determined inside this program-----------------

// Singles
double consumS[CONSUMDIM];   // consumption grid 
double cashS[CASHDIM];       // cash on hand grid
							 // Couples
double consumC[CONSUMDIM];   // consumption grid 
double cashC[CASHDIM];       // cash on hand grid
							 // other
double hsA[HSDIM];           // health status grid 
double IncomeA[IDIM];        // Permanent income grid, income as percentage ranking. 
							 // (See subroutine Grid for detail.) 

							 // Used to store markov chains 
double xiA[XIDIM], xiProbA[XIDIM];        // temporary health shock 
double xiProbAcdf[XIDIM + 1];               // JBJ 7/11/08               **** MDN 2014
double tempInv[XIDIM + RDIM];               // Placeholder: JBJ 7/11/08  **** added
double zetaA[ZETADIM];                    // persistent health shock 
double zetaProbM[ZETADIM][ZETADIM];
double zetaInv[ZETADIM];                  // stationary dist.  
double zetaInvcdf[ZETADIM + 1];
double rA[RDIM], rProbA[RDIM];            // interest rate shock 
int zetaIndN;                             // added 08/12/04 
double zetaProbMcdf[ZETADIM][ZETADIM + 1];  // added 08/12/04 

											// *?#?* Differential treatment of singles and couples RM 01/2017
											// income after tax at brackets  
											//double incomeBrkS[taxDim-1];
											//double incomeBrkC[taxDim-1];   

											// OLD 2014 version: double incomeBrk[taxDim-1];   

											// utility matrix  
double utilitySM[HSDIM][CONSUMDIM];         // single
double utilityCM[HSDIM][HSDIM][CONSUMDIM];  //couple

											// bequest GRID, one dies with a a surviving spouse
double bequestHWM[CASHDIM][BEQUESTDIM];

// expected UTILITY from bequest 
// *?#?* remove the consumption dimensionn from bequestUHWM as now really definded on next period coh 08/17 RM
double bequestUHWM[CASHDIM][BEQUESTDIM];  // one dies with a surviving spouse 

										  //The following two matrices are effectively expected utility matrices accounting for end of life expenses (as this varies with PI and zeta it should matter)
										  //  *?#?* changed 08/2017 RM  *?#?* Updated RM 09/17 to allow for dependence on lagged health *?#?* Updated RM 09/17 to allow for dependence on lagged health
										  //  *?#?* changed 01/2018 RM removed t subscript and instead precompute and store each time period of solution.
double bequestUCM[CASHDIM][IDIM][HSDIM][HSDIM][ZETADIM][CONSUMDIM];               // both die at the same time 
																				  //  *?#?* added 01/2017 RM  *?#?* Updated RM 09/17 to allow for dependence on lagged health
double bequestUSM[2][CASHDIM][IDIM][HSDIM][ZETADIM][CONSUMDIM];               // death for the single household

																			  // value function for singles
double valueFunSM[2][TDIMS + 1][IDIM][HSDIM][ZETADIM][CASHDIM];

// value function for couples
// add one more row at TDIMC corresponding to age T+1
double valueFunCM[TDIMC + 1][IDIM][HSDIM][HSDIM][ZETADIM][CASHDIM];

// consumption policy function matrix 
double consumFunSM[2][TDIMS][IDIM][HSDIM][ZETADIM][CASHDIM];
double consumFunCM[TDIMC][IDIM][HSDIM][HSDIM][ZETADIM][CASHDIM];

// bequest policy function matrix when husband/wife dies first  
double bequestFunSM[2][TDIMS][IDIM][HSDIM][ZETADIM][CASHDIM];      // singles 
																   // *?#?* removed diers health stat 08/17
																   /* The bequest functions for couples are indexed on the age of the couple at the very end of the previous period----CONSIDER CHANGING IN THE FUTURE
																   (CAN PRECALCULATE AFTER SINGLES SOLUTION, BUT BEFORE COUPLES AND USE MRS CONDITION?)
																   This means when viewing output, bequestFunWM[TDIMC]... is going to be never used in the model (0 probability event that
																   husband survives into the final period+1). If we were to define it on the age of the single we'd have the same problem with
																   bequestFunWM[0]. But I am open to changing this in the future- *?#?* RM*/
double bequestFunWM[TDIMC][IDIM][HSDIM][ZETADIM][CASHDIM];  // Couples when the wife dies first
double bequestFunHM[TDIMC][IDIM][HSDIM][ZETADIM][CASHDIM];  //Couples when the husband dies first
double bequestFunCM[TDIMC][IDIM][HSDIM][HSDIM][ZETADIM][CASHDIM];  //Couples when they both die


struct result
{
	int Ind1;
	double weight;
};
#if(TESTCHECKS==1)
//USED IN TESTING: *?#?*  Added by RM 06/17
// Euler Equation Errors for singles. For the sign matrix>0 Implies tha the consumption today is greater 
// than than the inverted marginaly utility evaluated at discounted expected marginal utility tomorrow
// add one more row at TDIMS corresponding to age T+1
double EulerErrorAbsSM[2][TDIMS + 1][IDIM][HSDIM][ZETADIM][CASHDIM];
double EulerErrorSignSM[2][TDIMS + 1][IDIM][HSDIM][ZETADIM][CASHDIM];

// Euler Equation Errors for couples. For the sign matrix>0 Implies tha the consumption today is greater 
// than than the inverted marginaly utility evaluated at discounted expected marginal utility tomorrow
// add one more row at TDIMS corresponding to age T+1
double EulerErrorAbsCM[TDIMC + 1][IDIM][HSDIM][HSDIM][ZETADIM][CASHDIM];
double EulerErrorSignCM[TDIMC + 1][IDIM][HSDIM][HSDIM][ZETADIM][CASHDIM];

double BeqErrorSignWM[TDIMC][IDIM][HSDIM][ZETADIM][CASHDIM];
double BeqErrorAbsWM[TDIMC][IDIM][HSDIM][ZETADIM][CASHDIM];
double BeqErrorSignHM[TDIMC][IDIM][HSDIM][ZETADIM][CASHDIM];
double BeqErrorAbsHM[TDIMC][IDIM][HSDIM][ZETADIM][CASHDIM];
#endif
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// functions used in main

//  Converts vectors to matrices and vice-versa
GMatrix zeromat(unsigned int recsize);
void switchem(double** dataPtr, double** tempPtr);
double** SetUpSim(double* dataVec, int extrayears);
void FreeSim(double* dataVec, int extrayears, double** dataMat); //*?#? added RM 11/17

																 //  GAUSS-C++ I/O programs written by K. Housinger 
unsigned char* gread(unsigned char* inbuf, int bytes, int byte_reverse, int bit_reverse);
GMatrix gau5read(char* fmt);
void gau5write(char* fmt, GMatrix mat); // reads vector from hard drive

										//   Update global parameters with values passed in from GAUSS
int globderef(double* prefvecPtr, double* asstvecPtr, double* hcostvecPtr,
	double* simvecPtr, double* agevecPtr, double* switchvecPtr);

// *?#?* Modified by RM 10/2022 to include no risk case for singles
int GetProfilesNEW(double* agevecPtr,
	double* hstrans_coeffsPtr, double* lnhc_meanPtr, double* lnhc_varPtr, double* lnhc_mean_noriskPtr, double* lnhc_var_noriskPtr,
	double* yprofPtr, double* yprofPIPtr);


double GetTransProbs(double** hsCoeffs, double age, int sexInd,
	double PInc, int healthStat, double HSProbs[HSDIM], int couplestatus);

double XtimesBeta(double* coeffs, double age, int sexInd, double PInc, int healthStat, int couplestatus);
//updated RM 09/17 for lagged healthcosts
double XtimesBeta_HCOST(double* coeffs, double age, int sexInd, double PInc, int laghealthStatH, int laghealthStatW, int healthStatH, int healthStatW, int couplestatus);
/* 2014 version:
int GetProfiles(double *agevecPtr, double *mnlnhcSPtr, double *mnlnhcCPtr,
double *stdlnhcSPtr, double *stdlnhcCPtr, double *hcostPIPtr,
double *mortrateSPtr, double *mortrateCPtr, double *mortratePIPtr,
double *hstranSPtr, double *hstranCPtr, double *hstranPIPtr,
double *yprofPtr, double *yprofPIPtr);
*/
//int GetProfiles(double *agevecPtr, double *mnlnhcSPtr, double *mnlnhcCPtr, 
//            double *stdlnhcSPtr, double *stdlnhcCPtr, double *hcostPIPtr, 
//            double *mortrateSPtr, double *mortrateCPtr, double *mortratePIPtr,
//            double *hstranSPtr, double *hstranCPtr, double *hstranPIPtr, 
//            double *yprofPtr, double *yprofPIPtr); // **** old version

// Updates first stage estimates- decleration rewritten to incorporate all of the necessary profiles (LTC & COUPLES) -01/2017 RM
int GetProfiles(double* agevecPtr, double* mnlnhcSPtr, double* stdlnhcSPtr,
	double* hcostSPIPtr, double* mortrateSPtr, double* mortrateSPIPtr,
	double* hstranSPtr, double* hstranSPIPtr, double* yprofSPtr,
	double* yprofSPIPtr, double* mnlnhcCPtr, double* stdlnhcCPtr,
	double* hcostCPIPtr, double* mortrateCPtr, double* mortrateCPIPtr,
	double* hstranCPtr, double* hstranCPIPtr, double* yprofCPtr,
	double* yprofCPIPtr);


double LogitSQRT(double x);
double Logit(double x);
double Multi3Logit(double x, double y); // *?#?* Created RM 01/2017

										//
										//void TwoYearToOneYear(double gg, double bb, double *_g, double *_b); 

										// create grids for cash on hand and consumption    
void Grid(double lambdacashS, double lambdacashC, double lambdaconsS, double lambdaconsC, double cashS[CASHDIM], double consumS[CONSUMDIM], double cashC[CASHDIM], double consumC[CONSUMDIM], double hsA[HSDIM], double IncomeA[IDIM]);
void GridBeq(double bequestHWM[CASHDIM][BEQUESTDIM]);

//discretize AR(1)and iid processes into Markov chain 
void Discretization(int n, double rho, double mu, double sigma, double zArray[ZETADIM], double* piMatrixP, double* piInvarV);
// JBJ: 7/11/08  // ****
// Singles, define Utility from consumption matrix   
void GetUtilityS(double utilitySM[HSDIM][CONSUMDIM]);

// Singles, define Utility from bequest matrix    *?#?* Replaced BequestUM with BequestUSM 01/2017
//*?#?* change to correctly get end of life costs RM 08/17 //*?#?* scrambling of asset grid in parallel RM 08/17
void GetUtilityBeqS(double bequestUSM[2][CASHDIM][IDIM][HSDIM][ZETADIM][CONSUMDIM], int iAssetsmin, int iAssetsmax, int* assetAssignments, int tInd);

// Couples, define Utility from consumption matrix  
void GetUtilityC(double utilityCM[HSDIM][HSDIM][CONSUMDIM]);

//*?#?* change to correctly get end of life costs RM 08/17
// Couples, define Utility from bequest matrix    //*?#?* scrambling of asset grid in parallel RM 08/17

//*?#?* change to eliminate t dependence. Compute these expected bequests at each age when solving RM 01/18
void GetUtilityBeqHW(double bequestUHWM[CASHDIM][BEQUESTDIM], int iAssetsmin, int iAssetsmax, int* assetAssignments);
void GetUtilityBeqUCM(double bequestUCM[CASHDIM][IDIM][HSDIM][HSDIM][ZETADIM][CONSUMDIM], int iAssetsmin, int iAssetsmax, int* assetAssignments, int tInd);

// after-tax income at bracket points  
//void IncomeAtBrk(double taxBrk[taxDim-1], double taxMar[taxDim], double incomeBrk[taxDim-1]);

// Interpolation and extrapolation 
double Interpolation(double* fP, double* xP, double x, int DIM);
int Locate(double* Xarray, double x, int DIM);
struct result GetLocation(double* xP, double x, int DIM);

void WriteData(double** assetsimMat, double** netIncomesimMat, double** consumptionsimMat,
	double** healthcostsimMat, double** zetaindexsimMat, double** marstatsimMat,
	GMatrix agesim96Ptr, GMatrix PIsim96Ptr, double** healthsimhMat,
	double** healthsimwMat);

void GetRulesSingle(int iAssetsmin, int iAssetsmax, int* assetAssignments); //*?#?* scrambling of asset grid in parallel RM 08/17

double GetValueSingle(int i, int tInd, int IInd, int hsInd, int zetaInd,
	int cashInd, int consumInd);
void GetBeqRulesCouples(int tInd, int iAssetsmin, int iAssetsmax, int* assetAssignments); //*?#?* scrambling of asset grid in parallel RM 08/17
void GetRulesCouples(int iAssetsmin, int iAssetsmax, int* assetAssignments); //*?#?* scrambling of asset grid in parallel RM 08/17
double GetValueCouples(int tInd, int IInd, int hsHInd, int hsWInd, int zetaInd, int cashInd,
	int consumInd);
// Consider a couple in which only one spouse dies
// bequestHMax is the bequest to others when the first member dies, given the couple's consumption choice
// There is an optimal bequest amount conditional on each consumption level for the couple before the death.

void simulation(GMatrix zetacdfsim96Ptr, GMatrix PIsim96Ptr, GMatrix agesim96Ptr, GMatrix incomesim96Ptr, GMatrix assetsim96Ptr,
	double** cohsimMat, double** assetsimMat, double** netIncomesimMat,
	double** consumptionsimMat, double** healthsimhMat, double** healthsimwMat,
	double** marstatsimMat, double** xicdfsimMat, double** epsiloncdfsimMat,
	double** healthcostsimMat, double** zetaindexsimMat, double** zetasimMat,
	double** xiindexsimMat, double** xisimMat, double** MedicaidsimMat,
	double* rorsim, double** beqsimMat, double** marstatsim2Mat,
	double** transfersimMat, double** initIndexsimMat, int iSimmin, int iSimmax); // JBJ: 7/11/08, 7/23/08, 5/6/09, 6/11/09 , RM 03/17
																				  // ****

																				  // *?#?* Added to pass control of zeta/xi dimensionality to gauss 08/2017 RM
int markovChnderef(double* zetavecPtr, int trueDim, double rho, double sigma_zeta,
	double* zetaA, double* zetaMatrixP, double* zetaInvarV);
void GetCdf(int nRows, int nCols, double* piMatrixP, double* piMatrixCDF);
void getInvar(int n, double* piMatrixP, double* piInvarV);
// JBJ: 7/11/08 
// **** 
// *?#?* Needed for changes to the calculation of bequests 08/2017 RM
void GetFinalMemberDeathCosts(double deathcostsFinalMemberC[TDIMC + 1][IDIM][HSDIM][HSDIM][ZETADIM][XIDIM], double deathcostsFinalMemberS[2][TDIMS + 1][IDIM][HSDIM][ZETADIM][XIDIM], int hardcode);

int* getAssignmentVec(int numPoints, int numNodes); // Improves efficiency when parallelizing.  From JBJ:  5/30/14. *?#?* Added RM 08/17

													/* older version

													void simulation(GMatrix zetasim96Ptr,  GMatrix PIsim96Ptr,  GMatrix agesim96Ptr, double **cohsimMat,
													double **assetsimMat,  double **netIncomesimMat, double **consumptionsimMat,
													double **healthsimhMat, double **healthsimwMat, double **marstatsimMat,
													double **xisimMat, double **epsilonsimMat, double **healthcostsimMat,
													double **zetaindexsimMat, double *rorsim, double **beqsimMat, int iSimmin, int iSimmax);

													void GetCdf();
													*/
double AfterTaxIncomeS(double y);
double AfterTaxIncomeC(double y);
double AvgTaxRateIncomeC(double y);
double AvgTaxRateIncomeS(double y);
double MargChange2AvgTaxIncomeC(double y);
double MargChange2AvgTaxIncomeS(double y);


//FUNCTIONS USED IN TESTING
void GetErrorsSingle(int iAssetsmin, int iAssetsmax);
double GetMarginalSingle(int i, int tInd, int  IInd, int hsInd, int zetaInd, int cashInd);
void GetErrorsCouples(int iAssetsmin, int iAssetsmax);
double GetMarginalCouples(int tInd, int IInd, int hsHInd, int hsWInd, int zetaInd, int cashInd);
void GetBeqErrorCouples(int tInd, int iAssetsmin, int iAssetsmax);
void Testprint(void);
void copyit(double* permvec, double* tempvec, int recsize);

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// main program, note that everything before this is global 
void main(int argc, char* argv[])
{

	/*   GMatrix prefvecPtr, asstvecPtr, agevecPtr, simvecPtr, switchvecPtr,
	hstrans_coeffsPtr, lnhc_meanPtrPtr, lnhc_varPtrPtr,
	yprofSPtr, yprofSPIPtr, yprofCPtr, yprofCPIPtr, rorsimPtr,
	cohsim96Ptr, zetasim96Ptr, PIsim96Ptr, agesim96Ptr, healthsimhPtr,
	healthsimwPtr, marstatsimPtr, xisimPtr, epsilonsimPtr, cohsimPtr,
	assetsimPtr, healthcostsimPtr, zetaindexsimPtr, consumptionsimPtr,
	beqsimPtr, netIncomesimPtr, zetacdfsim96Ptr, xicdfsimPtr, epsiloncdfsimPtr,
	xiindexsimPtr, zetasimPtr, MedicaidsimPtr, marstatsim2Ptr, transfersimPtr;
	*/
	// RM 10/21/22 updated to include norisk below *?#?* 
	GMatrix hstrans_coeffsPtr, lnhc_meanPtrPtr, lnhc_varPtrPtr, lnhc_mean_noriskPtrPtr, lnhc_var_noriskPtrPtr;
	// *?#?* Added inital states RM 11/2017
	GMatrix prefvecPtr, asstvecPtr, agevecPtr, simvecPtr, switchvecPtr,
		hcostvecPtr,
		yprofPtr, yprofPIPtr, rorsimPtr, xivecPtr, zetavecPtr,
		assetsim96Ptr, incomesim96Ptr, PIsim96Ptr, agesim96Ptr, healthsimhPtr,
		healthsimwPtr, marstatsimPtr, xisimPtr, cohsimPtr,
		assetsimPtr, healthcostsimPtr, zetaindexsimPtr, consumptionsimPtr,
		beqsimPtr, netIncomesimPtr, zetacdfsim96Ptr, xicdfsimPtr, epsiloncdfsimPtr,
		xiindexsimPtr, zetasimPtr, MedicaidsimPtr, marstatsim2Ptr, transfersimPtr, initIndexsimPtr;

	/* OLD VERSION *?#?* Added new GMatrix declerations for data and pointers for simulation data RM 01/2017

	GMatrix prefvecPtr, asstvecPtr, agevecPtr, simvecPtr, switchvecPtr,
	hcostvecPtr, mnlnhcSPtr, mnlnhcCPtr, stdlnhcSPtr, stdlnhcCPtr,
	hcostSPIPtr, hcostCPIPtr, mortrateSPtr, mortrateCPtr, mortrateSPIPtr,
	mortrateCPIPtr, hstranSPtr, hstranCPtr, hstranSPIPtr, hstranCPIPtr,
	yprofSPtr, yprofSPIPtr, yprofCPtr, yprofCPIPtr, rorsimPtr,
	cohsim96Ptr, zetasim96Ptr, PIsim96Ptr, agesim96Ptr, healthsimhPtr,
	healthsimwPtr, marstatsimPtr, xisimPtr, epsilonsimPtr, cohsimPtr,
	assetsimPtr, healthcostsimPtr, zetaindexsimPtr, consumptionsimPtr,
	beqsimPtr, netIncomesimPtr, zetacdfsim96Ptr, xicdfsimPtr, epsiloncdfsimPtr,
	xiindexsimPtr, zetasimPtr, MedicaidsimPtr, marstatsim2Ptr, transfersimPtr;

	*/


	// Added declerations for zetacdfsim96Ptr, xicdfsimPtr,epsiloncdfsimPtr, zetasimPtr, xiindexsimPtr , 
	// MedicaidsimPtr, marstatsim2Ptr, transfersimPtr,hcostSPIPtr, mortrateSPIPtr, hstranSPIPtr, yprofSPtr, yprofSPIPtr,
	// hcostCPIPtr,mortrateCPIPtr, hstranCPIPtr, yprofCPtr, yprofCPIPtr    

	// Old 2014 version:        
	// GMatrix prefvecPtr, asstvecPtr, agevecPtr, simvecPtr, switchvecPtr, 
	//         hcostvecPtr, mnlnhcSPtr, mnlnhcCPtr, stdlnhcSPtr, stdlnhcCPtr, 
	//         hcostPIPtr, mortrateSPtr, mortrateCPtr, mortratePIPtr, hstranSPtr, 
	//         hstranCPtr, hstranPIPtr, yprofPtr, yprofPIPtr, rorsimPtr, 
	//         cohsim96Ptr, zetasim96Ptr, PIsim96Ptr, agesim96Ptr, healthsimhPtr, 
	//         healthsimwPtr, marstatsimPtr, xisimPtr, epsilonsimPtr, cohsimPtr, 
	//         assetsimPtr, healthcostsimPtr, zetaindexsimPtr, consumptionsimPtr, 
	//         beqsimPtr, netIncomesimPtr;

	// *?#?* Added new pointer to pointer declerations for simulation matrices data RM 01/2017
	// *?#?* Added inital states RM 11/2017
	double** cohsimMat, ** assetsimMat, ** netIncomesimMat, ** consumptionsimMat,
		** healthsimhMat, ** healthsimwMat, ** marstatsimMat, ** xisimMat,
		** healthcostsimMat, ** zetaindexsimMat, ** beqsimMat,
		** zetasimMat, ** xiindexsimMat, ** MedicaidsimMat, ** marstatsim2Mat,
		** transfersimMat, ** xicdfsimMat, ** epsiloncdfsimMat, ** initIndexsimMat;


	// Old 2014 version:        
	// double **cohsimMat, **assetsimMat, **netIncomesimMat, **consumptionsimMat, 
	//        **healthsimhMat, **healthsimwMat, **marstatsimMat, **xisimMat, 
	//        **epsilonsimMat, **healthcostsimMat, **zetaindexsimMat, **beqsimMat;

	// Added declerations for  pointers to the matricies zetasimMat, xiindexsimMat, MedicaidsimMat,
	// marstatsim2Mat, transfersimMat, xicdfsimMat, epsiloncdfsimMat, 


	double* tempvec;
	//For simulation initial conditions
	int initindex;
	double* tempvec2;

	int gotderef, gotprofiles, yearInd, recsize;
	char fullpath[ADDRESS_LEN];

	double* rorsim; // define ror sequence in main. remember to change it.  

	clock_t start, end;  // recode time 
						 //int personInd; //dropped RM 11/17 as no lponger initialsie COH96 from GAUSS
	int rInd, zetaInd, xiInd;  // loop indices 

	int simspermachine, iAssetsmin, iAssetsmax, iSimmin, iSimmax, statespermachine;
	double spm2;

	int* assetAssignments; //*?#?* Added RM 08/17


	FILE* parameterP; // point to file containing parameters 

	if (useMPI == 0)  //  PC 
	{
		if (switchJohn == 3)  // Rory on NEWPC
		{
			strcpy(rootdir, "/Model\\iofiles\\");
			strcpy(outputdir, "/Model\\output\\");
			strcpy(datadir, "/Model\\data\\");
		}
		else if (switchJohn == 2)  // Rory on OLD PC
		{
			strcpy(rootdir, "/Model\\iofiles\\");
			strcpy(outputdir, "/Model\\output\\");
			strcpy(datadir, "/Model\\data\\");
		}
		else if (switchJohn == 1)  // John is using in Richmond 
		{
			strcpy(rootdir, "E:\\wealth_couples\\iofiles\\");
			strcpy(outputdir, "E:\\wealth_couples\\output\\");
			strcpy(datadir, "E:\\wealth_couples\\data\\");
		}
		else
		{
			strcpy(rootdir, "d:\\cristina\\couplesavings\\compute\\iofiles\\");
			strcpy(outputdir, "d:\\cristina\\couplesavings\\compute\\output\\");
			strcpy(datadir, "d:\\cristina\\couplesavings\\compute\\data\\");
		}
	}
	else  //  Unix or Cluster
	{
		if (switchJohn == 3)  // Rory on NEW PC
		{
			strcpy(rootdir, "C:\\Dropbox\\ERIC_couples\\NewPC\\iofiles\\");
			strcpy(outputdir, "C:\\Dropbox\\ERIC_couples\\NewPC\\output\\");
			strcpy(datadir, "C:\\Dropbox\\ERIC_couples\\NewPC\\data\\");
		}
		else if (switchJohn == 2)  // Rory on LARS HANSEN
		{
			strcpy(rootdir, "C:\\Dropbox\\ERIC_couples\\LarsHansenRunsAtIFS\\iofiles\\");
			strcpy(outputdir, "C:\\Dropbox\\ERIC_couples\\LarsHansenRunsAtIFS\\output\\");
			strcpy(datadir, "C:\\Dropbox\\ERIC_couples\\LarsHansenRunsAtIFS\\data\\");
		}
		else if (switchJohn == 1)
		{
			strcpy(rootdir, "E:\\Users\\John\\wealth_couples\\iofiles\\");
			strcpy(outputdir, "E:\\Users\\John\\wealth_couples\\output\\");
			strcpy(datadir, "E:\\Users\\John\\wealth_couples\\data\\");
		}
		else
		{
			strcpy(rootdir, "/mnt/raid/mdenardi/wealth/iofiles/");
			strcpy(outputdir, "/mnt/raid/mdenardi/wealth/output/");
			strcpy(datadir, "/mnt/raid/mdenardi/wealth/data/");
		}
	}

	start = clock();
	rank = 1; // Global 
	size = 1;

	// MPI-specific Code: 
	//Begin the automated commenting *?#?*- Added control sequence RM 03/17
#if(MPI_COMMENT==1)
	if (useMPI == 2)
	{
		MPI_Init(&argc, &argv);
		MPI_Comm_size(MPI_COMM_WORLD, &size);
		MPI_Comm_rank(MPI_COMM_WORLD, &rank);
		printf("size=%3d rank=%3d\n", size, rank);
		fflush(stdout);
	}
#elif(MPI_COMMENT==2) //added RM *?#?* 11/17
	//  Get number of processors. 
	omp_set_num_threads(NUM_THREADS);
#pragma omp parallel 
	{   size = omp_get_num_threads(); }
	printf("Number of threads = %d\n", size);
#endif     //(MPI_COMMENT==1)

	// *?#?* 05/2017 updated to be compatible with new version of getProfiles where coefficients can depend on couple status and use coefficients directly 

	// Read in parameter vectors from the *.fmt files (read into memory as arrays) 
	prefvecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "prefvec.fmt"));
	asstvecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "asstvec.fmt"));
	agevecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "agevec.fmt"));
	switchvecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "swchvec.fmt"));
	simvecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "simvec.fmt"));
	hcostvecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "medexvec.fmt"));
	//Income profiles for couples and singles
	yprofPtr = gau5read(strcat(strcpy(fullpath, rootdir), "yprof.fmt"));
	yprofPIPtr = gau5read(strcat(strcpy(fullpath, rootdir), "y_pi.fmt"));

	//Coefficients on health transitions
	hstrans_coeffsPtr = gau5read(strcat(strcpy(fullpath, rootdir), "hscoefs.fmt"));

	//Coefficients on health transitions
	lnhc_meanPtrPtr = gau5read(strcat(strcpy(fullpath, rootdir), "mxmcoefs.fmt"));
	lnhc_varPtrPtr = gau5read(strcat(strcpy(fullpath, rootdir), "mxvcoefs.fmt"));

	// RM 10/21/22 Read in alternative profiles for risk free, note need only the mean
	lnhc_mean_noriskPtrPtr = gau5read(strcat(strcpy(fullpath, rootdir), "mxm_noriskcoefs.fmt"));
	lnhc_var_noriskPtrPtr = gau5read(strcat(strcpy(fullpath, rootdir), "mxv_noriskcoefs.fmt"));

	// *?#?* Added to pass control of zeta/xi dimensionality to gauss 08/2017 RM

	xivecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "xiparms.fmt"));
	zetavecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "zetaparms.fmt"));
	/*
	// *?#?* 01/2017 updated to be compatible with new version of getProfiles where coefficients can depend on couple status as well as intercept.

	// Read in parameter vectors from the *.fmt files (read into memory as arrays)
	prefvecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "prefvec.fmt"));
	asstvecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "asstvec.fmt"));
	agevecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "agevec.fmt"));
	switchvecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "swchvec.fmt"));
	simvecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "simvec.fmt"));
	hcostvecPtr = gau5read(strcat(strcpy(fullpath, rootdir), "hcostvec.fmt"));
	mnlnhcSPtr = gau5read(strcat(strcpy(fullpath, rootdir), "mnlnhcs.fmt"));
	mnlnhcCPtr = gau5read(strcat(strcpy(fullpath, rootdir), "mnlnhcc.fmt"));
	stdlnhcSPtr = gau5read(strcat(strcpy(fullpath, rootdir), "stdlnhcs.fmt"));
	stdlnhcCPtr = gau5read(strcat(strcpy(fullpath, rootdir), "stdlnhcc.fmt"));
	hcostSPIPtr = gau5read(strcat(strcpy(fullpath, rootdir), "hcpicoefs.fmt"));
	hcostCPIPtr = gau5read(strcat(strcpy(fullpath, rootdir), "hcpicoefc.fmt"));
	mortrateSPtr = gau5read(strcat(strcpy(fullpath, rootdir), "mortprfs.fmt"));
	mortrateCPtr = gau5read(strcat(strcpy(fullpath, rootdir), "mortprfc.fmt"));
	mortrateSPIPtr = gau5read(strcat(strcpy(fullpath, rootdir), "mort_pis.fmt"));
	mortrateCPIPtr = gau5read(strcat(strcpy(fullpath, rootdir), "mort_pic.fmt"));
	hstranSPtr = gau5read(strcat(strcpy(fullpath, rootdir), "hsprobs.fmt"));
	hstranCPtr = gau5read(strcat(strcpy(fullpath, rootdir), "hsprobc.fmt"));
	hstranSPIPtr = gau5read(strcat(strcpy(fullpath, rootdir), "heal_pis.fmt"));
	hstranCPIPtr = gau5read(strcat(strcpy(fullpath, rootdir), "heal_pic.fmt"));
	yprofSPtr = gau5read(strcat(strcpy(fullpath, rootdir), "yprofs.fmt"));
	yprofCPtr = gau5read(strcat(strcpy(fullpath, rootdir), "yprofc.fmt"));
	yprofSPIPtr = gau5read(strcat(strcpy(fullpath, rootdir), "y_pis.fmt"));
	yprofCPIPtr = gau5read(strcat(strcpy(fullpath, rootdir), "y_pic.fmt"));

	*/

	/* Old setup:
	// Read in parameter vectors from the *.fmt files (read into memory as arrays)
	prefvecPtr    = gau5read(strcat(strcpy(fullpath,rootdir),"prefvec.fmt"));
	asstvecPtr    = gau5read(strcat(strcpy(fullpath,rootdir),"asstvec.fmt"));
	agevecPtr     = gau5read(strcat(strcpy(fullpath,rootdir),"agevec.fmt"));
	switchvecPtr  = gau5read(strcat(strcpy(fullpath,rootdir),"swchvec.fmt"));
	simvecPtr     = gau5read(strcat(strcpy(fullpath,rootdir),"simvec.fmt"));
	hcostvecPtr   = gau5read(strcat(strcpy(fullpath,rootdir),"hcostvec.fmt"));
	mnlnhcSPtr    = gau5read(strcat(strcpy(fullpath,rootdir),"mnlnhcs.fmt"));
	mnlnhcCPtr    = gau5read(strcat(strcpy(fullpath,rootdir),"mnlnhcc.fmt"));
	stdlnhcSPtr   = gau5read(strcat(strcpy(fullpath,rootdir),"stdlnhcs.fmt"));
	stdlnhcCPtr   = gau5read(strcat(strcpy(fullpath,rootdir),"stdlnhcc.fmt"));
	hcostPIPtr    = gau5read(strcat(strcpy(fullpath,rootdir),"hcpicoef.fmt"));
	mortrateSPtr  = gau5read(strcat(strcpy(fullpath,rootdir),"mortprfs.fmt"));
	mortrateCPtr  = gau5read(strcat(strcpy(fullpath,rootdir),"mortprfc.fmt"));
	mortratePIPtr = gau5read(strcat(strcpy(fullpath,rootdir),"mort_pi.fmt"));
	hstranSPtr    = gau5read(strcat(strcpy(fullpath,rootdir),"hsprobs.fmt"));
	hstranCPtr    = gau5read(strcat(strcpy(fullpath,rootdir),"hsprobc.fmt"));
	hstranPIPtr   = gau5read(strcat(strcpy(fullpath,rootdir),"heal_pi.fmt"));
	yprofPtr      = gau5read(strcat(strcpy(fullpath,rootdir),"yprof.fmt"));
	yprofPIPtr    = gau5read(strcat(strcpy(fullpath,rootdir),"y_pi.fmt"));
	*/
	// Initialize parameters by assigning array elements to appropriate parameters 
	gotderef = globderef(prefvecPtr.data, asstvecPtr.data, hcostvecPtr.data,
		simvecPtr.data, agevecPtr.data, switchvecPtr.data);

	// Create grids for cash on hand, consumption, health status and income   
	Grid(LAMBDAcashS, LAMBDAcashC, LAMBDAconsS, LAMBDAconsC, cashS, consumS, cashC, consumC, hsA, IncomeA);
	// *?#?* 01/2017 removed type identifiers from call and changed macros due to case-sensitivity. Old call:
	// Grid(double lambdacashS, double lambdacashC, double lambdaconsS, double lambdaconsC, cashS, consumS, cashC, consumC, hsA, IncomeA);

	//Initialize profiles  *?#?* 05/2017 RM for compatibility with the coefficient approach to getProfiles. // *?#?* Modified by RM 10/2022 to include no risk case for singles
	gotprofiles = GetProfilesNEW(agevecPtr.data,
		hstrans_coeffsPtr.data, lnhc_meanPtrPtr.data, lnhc_varPtrPtr.data, lnhc_mean_noriskPtrPtr.data, lnhc_var_noriskPtrPtr.data,
		yprofPtr.data, yprofPIPtr.data);

	// Save dimensions to ASCII files so that matlab can transform output files into matrices 
	if ((useMPI < 2) || (rank == (size - 1)))
	{
		parameterP = fopen(strcat(strcpy(fullpath, outputdir), "parameter.txt"), "w");
		fprintf(parameterP, "%5d\n %5d\n %5d\n %5d\n %5d\n %5d\n %5d\n %5d\n %5d\n %5d\n %5.2lf\n %5.2lf\n %5.2lf\n %5.2lf\n %5.2f\n %5.2f\n %5.2f\n %5.2f\n %5.2f\n %5.2f\n %5.2f\n %5.2f\n %5.2f\n %5.2f\n %5.2f\n",
			IDIM, TDIMS, TDIMC, HSDIM, RDIM, ZETADIM, XIDIM, CASHDIM, CONSUMDIM, BEQUESTDIM, CASHMAX, cMinS, cMinC, delta[0], delta[1], beta, eta, nu, omega, phi0, phi1, phi2, k0, k1, k2);
		/* Items are
		- dimension of permanent income
		- dimension of age  for singles and couples
		- dimension of health status
		- dimension of interest rate
		- dimension of persistent component of health shock
		- dimension of temporary component of health shock
		- dimension of cash on hand
		- dimension of consumption
		- size of bequest grid
		- maximum cash on hand
		- cMin for singles
		- cMin for couples
		- delta, health dependence utility param
		- beta, discount factor
		- eta, economy of scale
		- nu, coefficient of relative risk aversion
		- weight on spousal continuation value
		- phi0, beq parameter weight
		- phi1, beq parameter weight
		- phi2, beq parameter weight
		- k0, beq parameter shifter (luxury vs necessity)
		- k1, beq parameter shifter (luxury vs necessity)
		- k2, beq parameter shifter (luxury vs necessity)
		*?#?* Fixed case-sensitivity of cMinC 01/2017
		*/
		fclose(parameterP);
	}
	//Added to pass control of zeta/xi dimensionality to gauss 08/2017 RM:
	if (switchZeta == 1)
	{
		/* discretize persistent AR(1) process zeta into Markov chain */
		//    Discretization(ZETADIM, rhoHc, 0.0, sigma_epsilon, zetaA, &zetaProbM[0][0], &zetaInv[0]); /* procedure revised:  JBJ: 9/18/08 */ 
		markovChnderef(zetavecPtr.data, ZETADIM, rhoHc, sigma_zeta, zetaA, &zetaProbM[0][0], &zetaInv[0]);  // Now read in from GAUSS.  JBJ:  07/13/14

	}
	else // no shocks
	{
		for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
		{
			zetaA[zetaInd] = 0.0;
			zetaInv[zetaInd] = 1.0 / ZETADIM; /* JBJ:  9/18/08 */
			for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
			{
				zetaProbM[zetaInd][zetaIndN] = 1.0 / ZETADIM;
			}
		}
	}

	GetCdf(ZETADIM, ZETADIM, &zetaProbM[0][0], &zetaProbMcdf[0][0]);  /* get conditional CDF of zeta:  JBJ 9/18/08 */
	GetCdf(1, ZETADIM, &zetaInv[0], &zetaInvcdf[0]);  /* get invariant CDF of zeta */

													  /* Transitory component of medex preference shock */
	if (switchXi == 1)
	{
		//    Discretization(XIDIM,0.0,0.0,sigma_xi, xiA, &xiProbA[0], &tempInv[0]); /* Revised:  JBJ 9/18/08 */
		markovChnderef(xivecPtr.data, XIDIM, 0, sigma_xi, xiA, xiProbA, &tempInv[0]); // Now read in from GAUSS.  JBJ:  07/13/14

	}
	else /* no shocks */
	{
		for (xiInd = 0; xiInd < XIDIM; xiInd++)
		{
			xiA[xiInd] = 0.0;
			xiProbA[xiInd] = 1.0 / XIDIM;
		}
	}

	GetCdf(1, XIDIM, &xiProbA[0], &xiProbAcdf[0]);  /* get CDF of xi:  JBJ 9/18/08 */
													/*
													OLD
													if (switchZeta==1)
													{
													// discretize persistent AR(1) process zeta into Markov chain
													// printf(" discretized persistent component zeta\n");
													Discretization(ZETADIM, rhoHc, 0.0, sigma_epsilon, zetaA, &zetaProbM[0][0], &zetaInv[0]);
													// procedure revised:  JBJ: 7/11/08   // ******
													//Discretization(ZETADIM, rhoHc, 0.0, sigma_epsilon, zetaA, &zetaProbM[0][0]);
													}
													else
													{
													for (zetaInd=0; zetaInd<ZETADIM; zetaInd++)
													{
													zetaA[zetaInd]=0.0;
													// zetaA[zetaInd]=zetaInd-1.0/ZETADIM;
													zetaInv[zetaInd]=1.0/ZETADIM; // JBJ:  7/11/08
													for (zetaIndN=0; zetaIndN<ZETADIM; zetaIndN++)
													{
													zetaProbM[zetaInd][zetaIndN]=1.0/ZETADIM;
													}
													}
													}

													GetCdf(ZETADIM, ZETADIM, &zetaProbM[0][0], &zetaProbMcdf[0][0]);
													// get conditional CDF of zeta:  JBJ 7/11/08  // ****
													GetCdf(1, ZETADIM, &zetaInv[0], &zetaInvcdf[0]);  // ****
													// get invariant CDF of zeta

													// On transitory component of health costs
													if (switchXi==1)
													{
													// printf(" discretized transitory component xi\n");
													Discretization(XIDIM,0.0,0.0,sigma_xi, xiA, &xiProbA[0], &tempInv[0]);
													// Revised:  JBJ 7/11/08  // ****
													// Discretization(XIDIM,0.0,0.0,sigma_xi, xiA, &xiProbA[0]);
													}
													else // no shocks
													{
													for (xiInd=0; xiInd<XIDIM; xiInd++)
													{
													xiA[xiInd]=0.0;
													xiProbA[xiInd]=1.0/XIDIM;
													}
													}

													GetCdf(1, XIDIM, &xiProbA[0], &xiProbAcdf[0]);  // get CDF of xi:  JBJ 7/11/08
													*/
													// ****

	if (switchR == 1) // on interest rate  
	{
		if (RDIM == 1)
		{
			if ((useMPI < 2) || (rank == (size - 1)))
			{
				printf("Dimension of RoR RDIM=%3d  RoR activated switchR=%3d\n", RDIM, switchR);
				printf("ONLY A SINGLE VALUE FOR RATE OF RETURN SHOCK");
				printf("SO switchR HAS NO EFFECT");
				fflush(stdout);
			}
		}
		// printf(" discretized interest rate r\n"); 
		Discretization(RDIM, 0.0, mu_r, sigma_r, rA, &rProbA[0], &tempInv[XIDIM]);
		// Revised:  JBJ 7/11/08  // ****
		// Discretization(RDIM,0.0,mu_r,sigma_r, rA, &rProbA[0]);  
	}
	else
	{
		for (rInd = 0; rInd < RDIM; rInd++)
		{
			rA[rInd] = mu_r;
			rProbA[rInd] = 1.0 / RDIM;
		}
	}

	// GetCdf();  // calculate CDF of zeta 
	GetFinalMemberDeathCosts(deathcostsFinalMemberC, deathcostsFinalMemberS, GOODHEALTH);

	// initialize matrices 
	GetUtilityS(utilitySM);      // Find utility from consumption matrix 

								 // *?#?* Differential treatment of singles and couples RM 01/2017. Use the same procedure just call it twice for each grid
								 //   IncomeAtBrk(taxBrkS, taxMarS, incomeBrkS); // after-tax income at bracket points  
								 //   IncomeAtBrk(taxBrkS, taxMarS, incomeBrkS); // after-tax income at bracket points  

								 //OLD 2014 version:
								 //IncomeAtBrk(taxBrk, taxMar, incomeBrk); // after-tax income at bracket points  

	if (useMPI == 2)
	{
		spm2 = ((double)CASHDIM) / ((double)size);
		statespermachine = (int)ceil(spm2);
		iAssetsmin = rank * statespermachine;
		iAssetsmax = (rank + 1) * statespermachine;
		if (iAssetsmax > CASHDIM) iAssetsmax = CASHDIM;

		spm2 = ((double)nsims) / ((double)size);
		simspermachine = (int)ceil(spm2);
		iSimmin = rank * simspermachine;
		iSimmax = (rank + 1) * simspermachine;
		if (iSimmax > nsims) iSimmax = nsims;

	}
	else
	{
		iAssetsmin = 0;
		iAssetsmax = CASHDIM;

		iSimmin = 0;
		iSimmax = nsims;
	}
#if(MPI_COMMENT==2) //Added RM 11/17  *?#?* 
	spm2 = ((double)CASHDIM) / ((double)size);
	statespermachine = (int)ceil(spm2);
	spm2 = ((double)nsims) / ((double)size);
	simspermachine = (int)ceil(spm2);
#endif

	assetAssignments = getAssignmentVec(CASHDIM, size);   // Improves efficiency when parallelizing.  JBJ:  5/30/14 *?#?* Added RM 08/17

#if(MPI_COMMENT==2) //Added RM 11/17  *?#?* this 
#pragma omp parallel private(iAssetsmin,iAssetsmax,rank)
	{
		rank = omp_get_thread_num();
		iAssetsmin = rank * statespermachine;
		iAssetsmax = (rank + 1) * statespermachine;
		if (iAssetsmax > CASHDIM) iAssetsmax = CASHDIM;

		//*?#? removed precomputation of single-->death bequest utility and instead compute at each t in getrulessingle
		GetRulesSingle(iAssetsmin, iAssetsmax, assetAssignments); //*?#?* scrambling of asset grid in parallel RM 08/17

		if ((useMPI < 2) || (rank == (size - 1)))printf("Finished with decision rules for singles. rank=%d \n ", rank);
		fflush(stdout);

#if (TESTCHECKS == 1) //Generate euler Equation errors *?#?*  Added by RM 06/17

		GetErrorsSingle(iAssetsmin, iAssetsmax);
#endif //TESTCHECKS 

	}
#else //not the case that we use openMP

														  //*?#? removed precomputation of single-->death bequest utility and instead compute at each t in getrulessingle
	GetRulesSingle(iAssetsmin, iAssetsmax, assetAssignments); //*?#?* scrambling of asset grid in parallel RM 08/17
	if ((useMPI < 2) || (rank == (size - 1)))printf("Finished with decision rules for singles. rank=%d \n ", rank);
	fflush(stdout);

#if (TESTCHECKS == 1) //Generate euler Equation errors *?#?*  Added by RM 06/17


	GetErrorsSingle(iAssetsmin, iAssetsmax);
#endif //TESTCHECKS

#endif




	if (switchCouple == 1)
	{
		GridBeq(bequestHWM);    // bequest choice grid for case where there is a surviving spouse 
		GetUtilityC(utilityCM); // Find utility from consumption matrix   

#if(MPI_COMMENT==2) //Added RM 11/17  *?#?* this controls conditional compile for openMP case  
#pragma omp parallel private(iAssetsmin,iAssetsmax,rank)
		{
			rank = omp_get_thread_num();
			iAssetsmin = rank * statespermachine;
			iAssetsmax = (rank + 1) * statespermachine;
			if (iAssetsmax > CASHDIM) iAssetsmax = CASHDIM;
			GetUtilityBeqHW(bequestUHWM, iAssetsmin, iAssetsmax, assetAssignments); // find utility from bequest matrix for one spouse death  //*?#?* scrambling of asset grid in parallel RM 01/18
			GetRulesCouples(iAssetsmin, iAssetsmax, assetAssignments); //*?#?* scrambling of asset grid in parallel RM 08/17
			if ((useMPI < 2) || (rank == (size - 1)))printf("Finished with decision rules for couples. rank=%d \n ", rank);
			fflush(stdout);

#if (TESTCHECKS == 1) //Generate euler Equation errors *?#?*  Added by RM 06/17
			GetErrorsCouples(iAssetsmin, iAssetsmax);
#endif //testchecks
		}  //openMP pragma
#else //not the case that we use openMP

		GetUtilityBeqHW(bequestUHWM, iAssetsmin, iAssetsmax, assetAssignments); // find utility from bequest matrix for one spouse death  //*?#?* scrambling of asset grid in parallel RM 01/18

		GetRulesCouples(iAssetsmin, iAssetsmax, assetAssignments); //*?#?* scrambling of asset grid in parallel RM 08/17
		if ((useMPI < 2) || (rank == (size - 1)))printf("Finished with decision rules for couples. rank=%d \n ", rank);
		fflush(stdout);

#if (TESTCHECKS == 1) //Generate euler Equation errors *?#?*  Added by RM 06/17
		GetErrorsCouples(iAssetsmin, iAssetsmax);
#endif //testchecks
#endif //on openmp
	}
	//Added RM 11/17 *?#?*
	free(assetAssignments);

	// load simulated inputs 

	// zetasim96Ptr  = gau5read(strcat(strcpy(fullpath,rootdir),"ztasim96.fmt")); // simulated zeta at 1994 
	PIsim96Ptr = gau5read(strcat(strcpy(fullpath, rootdir), "pisim96.fmt"));  // simulated permanent income at 1994 
	agesim96Ptr = gau5read(strcat(strcpy(fullpath, rootdir), "agesim96.fmt")); // simulated age at 1994 
																			   // read in whole history   //****
	healthsimhPtr = gau5read(strcat(strcpy(fullpath, rootdir), "healsimh.fmt")); // simulation of health status for males 
	healthsimwPtr = gau5read(strcat(strcpy(fullpath, rootdir), "healsimw.fmt")); // simulation of health status for females 
	marstatsimPtr = gau5read(strcat(strcpy(fullpath, rootdir), "mstatsim.fmt")); // simulation of marital status 
																				 // The 3 lines below were changed by JBJ:  7/23/08 
	zetacdfsim96Ptr = gau5read(strcat(strcpy(fullpath, rootdir), "ztacdfsim96.fmt")); // simulated zeta in 1996 
	xicdfsimPtr = gau5read(strcat(strcpy(fullpath, rootdir), "xicdfsim.fmt"));    // simulation of transitory part of health cost 
	epsiloncdfsimPtr = gau5read(strcat(strcpy(fullpath, rootdir), "epscdfsim.fmt"));   // simulation of epsilon from uniform distribution 

	assetsim96Ptr = gau5read(strcat(strcpy(fullpath, rootdir), "asim96.fmt"));   // simulation of epsilon from uniform distribution 
	incomesim96Ptr = gau5read(strcat(strcpy(fullpath, rootdir), "incsim96.fmt"));   // simulation of epsilon from uniform distribution 

																					// older version of previous two blocks  
																					// healthsimhPtr = gau5read(strcat(strcpy(fullpath,rootdir),"healsimh.fmt")); // simulation of health status for husband 
																					// healthsimwPtr = gau5read(strcat(strcpy(fullpath,rootdir),"healsimw.fmt")); // simulation of health status for  wife 
																					// marstatsimPtr = gau5read(strcat(strcpy(fullpath,rootdir),"mstatsim.fmt")); // simulation of marital status 
																					// xisimPtr      = gau5read(strcat(strcpy(fullpath,rootdir),"xisim.fmt"));    // simulation of transitory part of health cost 
																					// epsilonsimPtr = gau5read(strcat(strcpy(fullpath,rootdir),"epssim.fmt"));   // simulation of epsilon from uniform distribution 


																					// Reshape array to matrix 
	healthsimhMat = SetUpSim(healthsimhPtr.data, 1); // first column: initial condition 
	healthsimwMat = SetUpSim(healthsimwPtr.data, 1); // first column: initial condition 
	marstatsimMat = SetUpSim(marstatsimPtr.data, 1); // first column: initial condition 
	xicdfsimMat = SetUpSim(xicdfsimPtr.data, 1);      /* transitory shock fill in entire history.  0->1: *?#?* added  RM 01/2017*/
	epsiloncdfsimMat = SetUpSim(epsiloncdfsimPtr.data, 1); /* shocks fed to the markov process, for entire history. 0->1: *?#?* addedRM 01/2017*/


														   // *?#?* Deleted following. "pointer matrix" is initalised below with reference to initial condition
														   // which is needed and with ptr.data initialised. Here it is not currently initialised  -RM 01/2017
														   //xisimMat      = SetUpSim(xisimPtr.data,0);      // no initial condition needed 
														   //epsilonsimMat = SetUpSim(epsilonsimPtr.data,0); // no initial condition needed 

														   // Set up matrices for storing simulation results 
	recsize = (TDimSims + 1) * nsims;
	beqsimPtr = zeromat(recsize);
	cohsimPtr = zeromat(recsize);
	healthcostsimPtr = zeromat(recsize);
	zetaindexsimPtr = zeromat(recsize); // JBJ:  7/11/08 
	zetasimPtr = zeromat(recsize); // JBJ:  7/11/08 
	xiindexsimPtr = zeromat(recsize); // JBJ:  7/23/08 
	xisimPtr = zeromat(recsize); // JBJ:  7/23/08 
	MedicaidsimPtr = zeromat(recsize); // JBJ:  7/23/08 
									   // zetaindexsimPtr   = zeromat(recsize); // ****
	consumptionsimPtr = zeromat(recsize);
	assetsimPtr = zeromat(recsize);
	netIncomesimPtr = zeromat(recsize);
	marstatsim2Ptr = zeromat(recsize); // JBJ:  5/6/09  
	transfersimPtr = zeromat(recsize); // JBJ:  6/11/09 
	initIndexsimPtr = zeromat(8 * nsims); // RM 11/17 *?#?* -8 as we have 8 items to pass 


										  // Reshape array to matrix 
	beqsimMat = SetUpSim(beqsimPtr.data, 1);
	healthcostsimMat = SetUpSim(healthcostsimPtr.data, 1);
	// zetaindexsimMat   = SetUpSim(zetaindexsimPtr.data,1);
	zetaindexsimMat = SetUpSim(zetaindexsimPtr.data, 1);// JBJ:  7/11/08 
	zetasimMat = SetUpSim(zetasimPtr.data, 1);     // JBJ:  7/11/08 
	xiindexsimMat = SetUpSim(xiindexsimPtr.data, 1);  // JBJ:  7/23/08 
	xisimMat = SetUpSim(xisimPtr.data, 1);       // JBJ:  7/23/08 
	MedicaidsimMat = SetUpSim(MedicaidsimPtr.data, 1); // JBJ:  7/23/08 
	consumptionsimMat = SetUpSim(consumptionsimPtr.data, 1);
	cohsimMat = SetUpSim(cohsimPtr.data, 1);
	assetsimMat = SetUpSim(assetsimPtr.data, 1);
	netIncomesimMat = SetUpSim(netIncomesimPtr.data, 1);
	marstatsim2Mat = SetUpSim(marstatsim2Ptr.data, 1); // JBJ:  5/6/09   
	transfersimMat = SetUpSim(transfersimPtr.data, 1); // JBJ:  6/11/09

													   // RM 11/17 *?#?* set up initial conditions -the 8 is the number of items in initial conditions
	initIndexsimMat = (double**)malloc((8) * sizeof(double*));
	for (initindex = 0; initindex < 8; initindex++)
	{
		initIndexsimMat[initindex] = &initIndexsimPtr.data[initindex * nsims];
	}


	/* Dropped RM 11/17 as now construct initial coh inside program not in GAUSS
	initialize first column of cohsimMat for initial condition
	for (personInd = 0; personInd<nsims; personInd++)
	cohsimMat[0][personInd] = cohsim96Ptr.data[personInd];
	*/
	rorsimPtr = gau5read(strcat(strcpy(fullpath, rootdir), "rorshk.fmt"));
	rorsim = rorsimPtr.data;
	for (yearInd = 0; yearInd < TDimSims + 1; yearInd++)
	{
		if (switchR == 0) rorsim[yearInd] = mu_r;
		else rorsim[yearInd] += mu_r;
	}
#if(MPI_COMMENT==2) //Use openMP
#pragma omp parallel private(iSimmin,iSimmax,rank)
	{
		rank = omp_get_thread_num();
		iSimmin = rank * simspermachine;
		iSimmax = (rank + 1) * simspermachine;
		if (iSimmax > nsims) iSimmax = nsims;
		printf("simulation starts for rank=%d\n", rank);

		simulation(zetacdfsim96Ptr, PIsim96Ptr, agesim96Ptr, incomesim96Ptr, assetsim96Ptr, cohsimMat, assetsimMat,
			netIncomesimMat, consumptionsimMat, healthsimhMat, healthsimwMat,
			marstatsimMat, xicdfsimMat, epsiloncdfsimMat, healthcostsimMat,
			zetaindexsimMat, zetasimMat, xiindexsimMat, xisimMat, MedicaidsimMat,
			rorsim, beqsimMat, marstatsim2Mat, transfersimMat, initIndexsimMat, iSimmin, iSimmax);

		printf("simulation ends for rank=%d\n", rank);
#pragma omp barrier //wait until every processor has hit this point
	} //On openMP pragma
#else //not using openmp
	printf("simulation starts for rank=%d\n", rank);

	simulation(zetacdfsim96Ptr, PIsim96Ptr, agesim96Ptr, incomesim96Ptr, assetsim96Ptr, cohsimMat, assetsimMat,
		netIncomesimMat, consumptionsimMat, healthsimhMat, healthsimwMat,
		marstatsimMat, xicdfsimMat, epsiloncdfsimMat, healthcostsimMat,
		zetaindexsimMat, zetasimMat, xiindexsimMat, xisimMat, MedicaidsimMat,
		rorsim, beqsimMat, marstatsim2Mat, transfersimMat, initIndexsimMat, iSimmin, iSimmax);
	printf("simulation ends for rank=%d\n", rank);
#endif //On openMP                                   
	// MPI-specific Code: 
	//Begin the automated commenting *?#?*- Added control sequence RM 03/17
	//Moved *?#?*-  RM 11/17
	tempvec = (double*)calloc(recsize, sizeof(double));
	tempvec2 = (double*)calloc(8 * nsims, sizeof(double));
#if(MPI_COMMENT==1)
	if (useMPI == 2)
	{
		MPI_Reduce((void*)cohsimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&cohsimPtr.data, &tempvec);

		MPI_Reduce((void*)assetsimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&assetsimPtr.data, &tempvec);

		MPI_Reduce((void*)netIncomesimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&netIncomesimPtr.data, &tempvec);

		MPI_Reduce((void*)zetaindexsimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&zetaindexsimPtr.data, &tempvec);

		MPI_Reduce((void*)zetasimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&zetasimPtr.data, &tempvec);

		MPI_Reduce((void*)xiindexsimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&xiindexsimPtr.data, &tempvec);

		MPI_Reduce((void*)xisimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&xisimPtr.data, &tempvec);

		MPI_Reduce((void*)MedicaidsimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&MedicaidsimPtr.data, &tempvec);

		MPI_Reduce((void*)healthcostsimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&healthcostsimPtr.data, &tempvec);

		MPI_Reduce((void*)consumptionsimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&consumptionsimPtr.data, &tempvec);

		MPI_Reduce((void*)beqsimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&beqsimPtr.data, &tempvec);

		//  Fixed by JBJ:  5/6/09
		MPI_Reduce((void*)marstatsim2Ptr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&marstatsim2Ptr.data, &tempvec);

		//  Added by JBJ:  6/11/09
		MPI_Reduce((void*)transfersimPtr.data, (void*)tempvec, recsize, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&transfersimPtr.data, &tempvec);
		// Added by RM 11/17 *?#?* -8 items
		MPI_Reduce((void*)initIndexsimPtr.data, (void*)tempvec2, 8 * nsims, MPI_DOUBLE,
			MPI_SUM, size - 1, MPI_COMM_WORLD);
		switchem(&initIndexsimPtr.data, &tempvec2);
	}
#endif     //(MPI_COMMENT==1)
	//*?#?*  Added by RM 11/17
	free(tempvec);
	free(tempvec2);

#if (TESTCHECKS == 1) //Generate euler Equation errors *?#?*  Added by RM 06/17
	Testprint();
#endif //testchecks

	if ((useMPI < 2) || (rank == (size - 1)))
	{
		WriteData(assetsimMat, netIncomesimMat, consumptionsimMat, healthcostsimMat, zetaindexsimMat,
			marstatsimMat, agesim96Ptr, PIsim96Ptr, healthsimhMat, healthsimwMat);

		gau5write(strcat(strcpy(fullpath, rootdir), "cohsim.fmt"), cohsimPtr);
		gau5write(strcat(strcpy(fullpath, rootdir), "asstsim.fmt"), assetsimPtr);
		gau5write(strcat(strcpy(fullpath, rootdir), "netIncomesim.fmt"), netIncomesimPtr);
		gau5write(strcat(strcpy(fullpath, rootdir), "ztasim.fmt"), zetasimPtr);            // JBJ:  7/23/08 
		gau5write(strcat(strcpy(fullpath, rootdir), "ztaindexsim.fmt"), zetaindexsimPtr);  // JBJ:  7/23/08 
		gau5write(strcat(strcpy(fullpath, rootdir), "xisim.fmt"), xisimPtr);               // JBJ:  7/23/08 
		gau5write(strcat(strcpy(fullpath, rootdir), "xiindexsim.fmt"), xiindexsimPtr);     // JBJ:  7/23/08  
		gau5write(strcat(strcpy(fullpath, rootdir), "Medicaidsim.fmt"), MedicaidsimPtr);   // JBJ:  7/23/08  
		gau5write(strcat(strcpy(fullpath, rootdir), "oopmedexsim.fmt"), healthcostsimPtr);
		gau5write(strcat(strcpy(fullpath, rootdir), "conssim.fmt"), consumptionsimPtr);
		gau5write(strcat(strcpy(fullpath, rootdir), "beqsim.fmt"), beqsimPtr);
		gau5write(strcat(strcpy(fullpath, rootdir), "mssim2.fmt"), marstatsim2Ptr);        // JBJ:  5/6/09   
		gau5write(strcat(strcpy(fullpath, rootdir), "transfersim.fmt"), transfersimPtr);   // JBJ:  6/11/09  
		gau5write(strcat(strcpy(fullpath, rootdir), "iIndexsim.fmt"), initIndexsimPtr);   //  RM 11/17 *?#?*

		end = clock();
		printf("Main section ends in %5d minutes %5d seconds \n ", (end - start) / CLOCKS_PER_SEC / 60,
			((end - start) / CLOCKS_PER_SEC) % 60);
	}
	//Added RM 11/17 to deallocate memory
	free(initIndexsimMat);


	FreeSim(healthsimhPtr.data, 1, healthsimhMat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(healthsimwPtr.data, 1, healthsimwMat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(marstatsimPtr.data, 1, marstatsimMat); // Deallocate memory RM 11/17 *?#?* 
	FreeSim(xicdfsimPtr.data, 1, xicdfsimMat);  // Deallocate memory RM 11/17 *?#?*
	FreeSim(epsiloncdfsimPtr.data, 1, epsiloncdfsimMat); // Deallocate memory RM 11/17 *?#?*

	FreeSim(beqsimPtr.data, 1, beqsimMat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(healthcostsimPtr.data, 1, healthcostsimMat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(zetaindexsimPtr.data, 1, zetaindexsimMat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(zetasimPtr.data, 1, zetasimMat);  // Deallocate memory RM 11/17 *?#?*
	FreeSim(xiindexsimPtr.data, 1, xiindexsimMat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(xisimPtr.data, 1, xisimMat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(MedicaidsimPtr.data, 1, MedicaidsimMat); // Deallocate memory RM 11/17 *?#?* 
	FreeSim(consumptionsimPtr.data, 1, consumptionsimMat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(cohsimPtr.data, 1, cohsimMat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(assetsimPtr.data, 1, assetsimMat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(netIncomesimPtr.data, 1, netIncomesimMat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(marstatsim2Ptr.data, 1, marstatsim2Mat); // Deallocate memory RM 11/17 *?#?*
	FreeSim(transfersimPtr.data, 1, transfersimMat); // Deallocate memory RM 11/17 *?#?*
													 // MPI-specific Code:  (JBJ: 7/23/08)  
													 //Begin the automated commenting *?#?*- Added control sequence RM 03/17
#if(MPI_COMMENT==1)
	MPI_Finalize();
#endif     //(MPI_COMMENT==1)

	if ((useMPI < 2) || (rank == (size - 1)))printf("This program ends in %5d minutes %5d seconds \n ", (end - start) / CLOCKS_PER_SEC / 60,
		((end - start) / CLOCKS_PER_SEC) % 60);

}   // End of main

	//--------------------------------------------------------------------------------
	//----------------------------------SUBROUTINES-----------------------------------

	// create grid for cash on hand and consumption    
	//  *?#?* Added comma missing in decleration and type for  cashC RM 01/2017
	// Old decleration:
	//void Grid(double lambdacashS, double lambdacashC, double lambdaconsS, double lambdaconsC, double cashS[CASHDIM], double consumS[CONSUMDIM], cashC[CASHDIM], double consumC[CONSUMDIM] double hsA[HSDIM], double IncomeA[IDIM])
	//
void Grid(double lambdacashS, double lambdacashC, double lambdaconsS, double lambdaconsC, double cashS[CASHDIM], double consumS[CONSUMDIM], double cashC[CASHDIM], double consumC[CONSUMDIM], double hsA[HSDIM], double IncomeA[IDIM])
{ // ***

	FILE* cashP; // used to print out stuff 
	char fullpath[ADDRESS_LEN];
	int cashInd, consumInd, IInd, hsInd;
	double lowValArith, highValArith, currValArith, incrArith;
	double trueIInd; //Added RM *?#?* 01/18

					 // Make grids for SINGLES
					 // COH *?#?*  --Replaced ADIM with CASHDIM 01/2017 RM
	lowValArith = pow(cMinS, 1.0 / lambdacashS);
	highValArith = pow(CASHMAX, 1.0 / lambdacashS);
	incrArith = (highValArith - lowValArith) / (CASHDIM - 1.0);
	// cash on hand
	currValArith = lowValArith;
	// create cash grid, cMin<=x<=CASHMAX 
	for (cashInd = 0; cashInd < CASHDIM; cashInd++)
	{
		cashS[cashInd] = pow(currValArith, lambdacashS);
		currValArith += incrArith;
	}
	// consumption
	lowValArith = pow(cMinS, 1.0 / lambdaconsS);
	highValArith = pow(CASHMAX, 1.0 / lambdaconsS);
	currValArith = lowValArith;
	incrArith = (highValArith - lowValArith) / (CASHDIM - 1.0); //*?#?*  --Added to allow for differing grid sizes 01/2017 RM
																// create consumption grid, cMin<=x<=CASHMAX 
	for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
	{
		consumS[consumInd] = pow(currValArith, lambdaconsS);
		currValArith += incrArith;
	}

	// Make grids for couples
	//COH  *?#?*  --Replaced ADIM with CASHDIM 01/2017 RM
	lowValArith = pow(cMinC, 1.0 / lambdacashC);
	highValArith = pow(CASHMAX, 1.0 / lambdacashC);
	incrArith = (highValArith - lowValArith) / (CASHDIM - 1.0);
	// cash on hand
	currValArith = lowValArith;
	// create cash grid, cMin<=x<=CASHMAX 
	for (cashInd = 0; cashInd < CASHDIM; cashInd++)
	{
		cashC[cashInd] = pow(currValArith, lambdacashC);
		currValArith += incrArith;
	}
	// consumption
	lowValArith = pow(cMinC, 1.0 / lambdaconsC);
	highValArith = pow(CASHMAX, 1.0 / lambdaconsC);
	currValArith = lowValArith;
	incrArith = (highValArith - lowValArith) / (CONSUMDIM - 1.0); //*?#?*  --Added to allow for differing grid sizes 01/2017 RM
																  // create consumption grid, cMin<=x<=CASHMAX 
	for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
	{
		consumC[consumInd] = pow(currValArith, lambdaconsC);
		currValArith += incrArith;
	}

	// Now onto other stuff
	//Added to allow for finer grid at extremes. RM 01/18 *?#?* 
	trueIInd = 0;

	for (IInd = 0; IInd < IDIM; IInd++)
	{
		IncomeA[IInd] = trueIInd / (IDIM - 3); // Income expressed as percentile ranking 
		if ((IInd < 2) || (IInd > (IDIM - 4))) { trueIInd += 0.5; }
		else { trueIInd += 1.0; }
	}
	/* OLD:
	for (IInd = 0; IInd<IDIM; IInd++)
	{
	IncomeA[IInd] = ((double)IInd) / (IDIM - 1); // Income expressed as percentile ranking
	}*/
	//IncomeA[1] = 0.2; //For testing against GAUSS  
	for (hsInd = 0; hsInd < HSDIM; hsInd++)
	{
		hsA[hsInd] = hsInd;
	}

	if ((useMPI < 2) || (rank == (size - 1)))  // write out grids to text files
	{  // singles COH grid
		cashP = fopen(strcat(strcpy(fullpath, outputdir), "xS.txt"), "w");

		for (cashInd = 0; cashInd < CASHDIM; cashInd++)
		{
			fprintf(cashP, "%10.3f\n", cashS[cashInd]);
		}

		fclose(cashP);
		// couples COHG grid
		cashP = fopen(strcat(strcpy(fullpath, outputdir), "xC.txt"), "w");

		for (cashInd = 0; cashInd < CASHDIM; cashInd++)
		{
			fprintf(cashP, "%10.3f\n", cashC[cashInd]);
		}

		fclose(cashP);
		cashP = fopen(strcat(strcpy(fullpath, outputdir), "consumS.txt"), "w");

		for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
		{
			fprintf(cashP, "%10.3f\n", consumS[consumInd]);
		}
		fclose(cashP);
		cashP = fopen(strcat(strcpy(fullpath, outputdir), "consumC.txt"), "w");

		for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
		{
			fprintf(cashP, "%10.3f\n", consumC[consumInd]);
		}
		fclose(cashP);
	}
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// Bequest grid needed when one member of a couple dies 
// *?#?* Replaced CONSUMDIS with CONSUMDIM & added missing ";"
// & Removed bequestfrac from decleration as it is never used in other parts of the code RM 01/2017
//old decleration
//void GridBeq(double bequestfrac[BEQUESTDIM], double bequestHWM[CASHDIM][CONSUMDIS][BEQUESTDIM])

void GridBeq(double bequestHWM[CASHDIM][BEQUESTDIM])
{
	int cashInd, bequestInd;
	double stuff;
	double bequestfrac[BEQUESTDIM];
	double lowValArith, highValArith, currValArith, incrArith;

	// Make grids for fraction of stuff left as bequests, as a fraction between 0 and 1
	lowValArith = 0.0;
	highValArith = 1.0;
	incrArith = (highValArith - lowValArith) / (BEQUESTDIM - 1);
	currValArith = lowValArith;
	for (bequestInd = 0; bequestInd < BEQUESTDIM; bequestInd++)
	{
		bequestfrac[bequestInd] = currValArith;
		currValArith += incrArith;
	}

	// *?#?* eliminating consumption choice & changed to single cash grid (due to 2 stage budgeting approach) RM 08/17
	// create grid, 0<=b<=x-c 
	for (cashInd = 0; cashInd < CASHDIM; cashInd++)
	{
		stuff = cashS[cashInd];
		for (bequestInd = 0; bequestInd < BEQUESTDIM; bequestInd++)
		{
			// *?#?* repklaced parenthesis qith square brackets- previously compiler expected a pointer RM 01/2017
			bequestHWM[cashInd][bequestInd] = stuff * bequestfrac[bequestInd];
		} // *?#?* reversed the order of braces - previously else came next causing errors RM 01/2017
	} //on the cash for

	  /*   // create grid, 0<=b<=x-c
	  for (cashInd=0; cashInd<CASHDIM; cashInd++)
	  {
	  for (consumInd=0; consumInd<CONSUMDIM; consumInd++)
	  {
	  if (consumS[consumInd]<=cashS[cashInd]|| fabs(consumS[consumInd]-cashS[cashInd]) <ABS_TOL) //THis allows the equality part to function for almost equal
	  // if (consumS[consumInd]<=cashS[cashInd]) *?#?*  Old version. Changed to above RM  06/2017
	  {
	  stuff=cashC[cashInd]-consumC[consumInd];
	  for (bequestInd=0; bequestInd<BEQUESTDIM; bequestInd++)
	  {
	  // *?#?* repklaced parenthesis qith square brackets- previously compiler expected a pointer RM 01/2017
	  bequestHWM[cashInd][consumInd][bequestInd] = stuff*bequestfrac[bequestInd];
	  } // *?#?* reversed the order of braces - previously else came next causing errors RM 01/2017
	  } //on the if
	  else
	  {
	  break;

	  }
	  } //consumption for
	  }  //cash for
	  */
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/* Records nodes and weights for Gauss-Hermite Quadrature
n: number of Gauss points to be used
xArray[j]: j-th point
wArray[j]: weight of the j-th point
Nodes and weights are from Judd(1999), page 266
*/
void Quadrature(int n, double xArray[], double wArray[])
{
	int j;

	if (n == 1)
	{
		xArray[0] = 0.0;
		wArray[0] = 1.0;
	}

	if (n == 2)
	{
		xArray[1] = 0.7071067811;
		wArray[1] = 0.8862269254;
	}

	if (n == 3)
	{
		xArray[1] = 0;
		wArray[1] = 1.181635900;
		xArray[2] = 1.224744871;
		wArray[2] = 0.2954089751;
	}

	if (n == 4)
	{
		xArray[3] = 1.650680123;
		wArray[3] = 0.08131293544;
		xArray[2] = 0.5246476232;
		wArray[2] = 0.8049140900;
	}

	if (n == 5)
	{
		xArray[4] = 2.020182870;
		wArray[4] = 0.01995324205;
		xArray[3] = 0.9585724646;
		wArray[3] = 0.3936193231;
		xArray[2] = 0;
		wArray[2] = 0.9453087204;
	}

	if (n == 6)
	{
		xArray[5] = 0.2350604973e1;
		wArray[5] = 0.4530009905e-2;
		xArray[4] = 0.1335849074e1;
		wArray[4] = 0.1570673203;
		xArray[3] = 0.4360774119;
		wArray[3] = 0.7246295952;
	}

	if (n == 7)
	{
		xArray[3] = 0;
		wArray[3] = 0.8102646175;
		xArray[4] = 0.8162878828;
		wArray[4] = 0.4256072526;
		xArray[5] = 1.673551628;
		wArray[5] = 0.05451558281;
		xArray[6] = 2.651961356;
		wArray[6] = 0.0009717812450;
	}

	if (n == 8)
	{
		xArray[7] = 0.2930637420e1;
		wArray[7] = 0.1996040722e-3;
		xArray[6] = 0.1981656756e1;
		wArray[6] = 0.1707798300e-1;
		xArray[5] = 0.1157193712e1;
		wArray[5] = 0.2078023258;
		xArray[4] = 0.3811869902;
		wArray[4] = 0.6611470125;
	}

	if (n == 10)
	{
		xArray[5] = 0.3429013272;
		wArray[5] = 0.6108626337;
		xArray[6] = 1.036610829;
		wArray[6] = 0.2401386110;
		xArray[7] = 1.756683649;
		wArray[7] = 0.03387439445;
		xArray[8] = 2.532731674;
		wArray[8] = 0.001343645746;
		xArray[9] = 3.436159118;
		wArray[9] = 0.000007640432855;
	}

	for (j = 0; j < (n / 2); j++)
	{
		xArray[j] = -xArray[n - 1 - j];
		wArray[j] = wArray[n - 1 - j];
	}
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/* Discretization using Gauss Quadrature
This program discretizes a AR(1) process with autoregressive coefficient
rho and standard normal innoviation with standard deviation sigma into a
n-point first-order markov chain following Tauchen and Hussey(1991).
z(t) = z(t-1)*rho+epsilon
epsilon ~ N(mu,sigma^2)
Also returns the invariant probability vector:  JBJ 7/11/08
*/

void Discretization(int n, double rho, double mu, double sigma, double zArray[ZETADIM],
	double* piMatrixP, double* piInvarV)
{
	int h, i, j, k;  // indices 

	double xArray[10];  // xArray[j]: j-th point,used in Quadrature 
	double wArray[10];  // wArray[j]: weight of the j-th point,used in Quadrature 
	double sum[10];
	double** ProductMat, ** subtot;

	int m;  /* number of rows. If rho = 0 then AR(1) process is a iid series, and
			we define m = 1, since every row is the same for transition matrix  */

	if ((fabs(sigma - 0.0) < ABS_TOL) || (fabs(rho - 1.0) < ABS_TOL))  // *?#?*  Changed to allow for double precision RM  06/2017
																   //if ((sigma==0)||(rho==1)) // not random: added 09/15.04  *?#?*  Old version. Changed to above RM  06/2017
	{
		for (i = 0; i < n; i++)
		{
			zArray[i] = mu;

			for (j = 0; j < n; j++)
			{
				*(piMatrixP + i * n + j) = 0;
			}
			*(piMatrixP + i * n + i) = 1;
		}
	}
	// detect errors 
	else if ((!((n == 1) || (n == 2) || (n == 3) || (n == 4) || (n == 5) || (n == 6) || (n == 7) || (n == 8) || (n == 10))) || ((rho > 1) || (fabs(rho - 1.0) < ABS_TOL) || (rho < 0.0)) || (sigma < 0.0))  //Test rho for greater than or within tol instead of GEQ
																																																	//else if ((!((n == 1) || (n == 2) || (n == 3) || (n == 4) || (n == 5) || (n == 6) || (n == 7) || (n == 8) || (n == 10))) || ((rho >= 1) || (rho<0)) || (sigma<0))  Old version. Changed to above RM  06/2017
	{

		printf("Error! The requirement for the AR(1) process is that the number of Guass points n=1, 2,3,4,5,7,10, the autoregession coefficiency 0<=rho<1 and the standard deviation sigma is positive.\n");
		fflush(stdout);
	}
	else
	{
		// find discrete points and weights associated with each point 
		Quadrature(n, xArray, wArray);

		/* transformation
		x = (z+mu/(rho-1))/(sqrt(2)*sigma)
		thus z = sqrt(2.0)*sigma*x-mu/(rho-1) */

		for (i = 0; i < n; i++)
		{
			zArray[i] = sqrt(2.0) * sigma * xArray[i] - mu / (rho - 1);
		}

		// calculate  and print transition matrix 
		if (fabs(rho - 0.0) < ABS_TOL) m = 1;          // iid process  
													 //  if ( rho ==0 ) m = 1;          // iid process   Old version. Changed to above RM  06/2017 

		else m = n;     // AR(1) process  

		for (i = 0; i < m; i++)
		{
			sum[i] = 0.0;
			for (j = 0; j < n; j++)
			{
				// sum is used to normalize transition matrix 
				sum[i] = sum[i] + wArray[j] * exp(pow(xArray[j], 2) - pow(xArray[j] - rho * xArray[i], 2)) / sqrt(PI);
			}
			for (j = 0; j < n; j++)
			{
				*(piMatrixP + i * n + j) = wArray[j] * exp(pow(xArray[j], 2) - pow(xArray[j] - rho * xArray[i], 2)) / sqrt(PI) / sum[i];
			}
		}
	} // end of else  

	  // Find stationary distribution using brute force, by repeatedly multiplying Pi by itself 

	ProductMat = (double**)malloc(n * sizeof(double*));
	subtot = (double**)malloc(n * sizeof(double*));
	for (i = 0; i < n; i++)
	{
		ProductMat[i] = (double*)malloc(n * sizeof(double));
		subtot[i] = (double*)calloc(n, sizeof(double));
		for (j = 0; j < n; j++)
		{
			ProductMat[i][j] = *(piMatrixP + i * n + j);
		}
	}

	for (h = 0; h < 500; h++)
	{
		for (i = 0; i < n; i++)
		{
			for (j = 0; j < n; j++)
			{
				subtot[i][j] = 0;
				for (k = 0; k < n; k++)
					subtot[i][j] += ProductMat[i][k] * (*(piMatrixP + k * n + j));
			}
		}

		for (i = 0; i < n; i++)
		{
			for (j = 0; j < n; j++)
			{
				ProductMat[i][j] = subtot[i][j];
			}
		}
	}

	for (i = 0; i < n; i++)
	{
		piInvarV[i] = ProductMat[0][i];
	}
}


//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// Define the utility matrix for singles 

void GetUtilityS(double utilitySM[HSDIM][CONSUMDIM])
{
	int hsInd = 0;
	int consumInd = 0; //  index 

					   // if (nu  ==  1.0)     // log utility OLD VERSION
	if (fabs(nu - 1.0) < ABS_TOL)     // log utility //*?#?* Now compares nearly the same 06/17 RM. Old Version above
	{
		for (hsInd = 0; hsInd < HSDIM; hsInd++)
		{
			for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
			{ //*?#?* Now uses delta vector 06/17 RM. Old Version:
			  // utilitySM[hsInd][consumInd] = (1+delta*hsA[hsInd])*log(consumS[consumInd]); 

				utilitySM[hsInd][consumInd] = (1 + delta[hsInd]) * log(consumS[consumInd]);
			}
		}
	}
	else
	{
		for (hsInd = 0; hsInd < HSDIM; hsInd++)
		{
			for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
			{//*?#?* Now uses delta vector 06/17 RM. Old Version:
			 //utilitySM[hsInd][consumInd] = (1+delta*hsA[hsInd])*pow(consumS[consumInd], 1-nu)/(1-nu); 
				utilitySM[hsInd][consumInd] = (1 + delta[hsInd]) * pow(consumS[consumInd], 1 - nu) / (1 - nu);
			}
		}
	}
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// Defines utility matrix for couples   

void GetUtilityC(double utilityCM[HSDIM][HSDIM][CONSUMDIM])
{
	int hsWInd = 0;
	int hsHInd = 0;
	int consumInd = 0; // 

					   // if (nu  ==  1.0)     // log utility OLD VERSION
	if (fabs(nu - 1.0) < ABS_TOL)     // log utility //*?#?* Now compares nearly the same 06/17 RM. Old Version above
	{
		for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
		{
			for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
			{
				for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
				{//*?#?* Now uses delta vector 06/17 RM. Old Version:
				 //  utilityCM[hsHInd][hsWInd][consumInd] = 
				 //     (1+delta*hsA[hsHInd]+1+delta*hsA[hsWInd])*log(consumC[consumInd]/eta); 
					utilityCM[hsHInd][hsWInd][consumInd] =
						(1 + delta[hsHInd] + 1 + delta[hsWInd]) * log(consumC[consumInd] / eta);

				}
			}
		}
	}
	else
	{
		for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
		{
			for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
			{
				for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
				{//*?#?* Now uses delta vector 06/17 RM. Old Version:
				 //             utilityCM[hsHInd][hsWInd][consumInd] = 
				 //      (1+delta*hsA[hsHInd]+1+delta*hsA[hsWInd])*pow(consumC[consumInd]/eta, 1-nu)/(1-nu); 

					utilityCM[hsHInd][hsWInd][consumInd] =
						(1 + delta[hsHInd] + 1 + delta[hsWInd]) * pow(consumC[consumInd] / eta, 1 - nu) / (1 - nu);
				}
			}
		}
	}
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/* Utility from bequest for a person with a surviving spouse
theta_j(b) = phi_j*( (b+k_j)^(1-nu) )/(1-nu) */

//*?#?* eliminated pointer notation as pointer not passed elesewhere
// (i.e. in GetUtilityBeqC) RM 01/2017 
double UBeqHW(double BequestP)
{
	double utils;
	// if (nu  ==  1.0)     // log utility OLD VERSION
	if (fabs(nu - 1.0) < ABS_TOL)     // log utility //*?#?* Now compares nearly the same 06/17 RM. Old Version above
		utils = phi1 * log(BequestP + k1);
	else
		utils = phi1 * pow(BequestP + k1, 1 - nu) / (1 - nu);
	return utils;
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/* Utility from bequest for a single person with a surviving spouse
theta_j(b) = phi_j*( (b+k_j)^(1-nu) )/(1-nu) */
//*?#?* eliminated pointer notation as pointer not passed elesewhere
// (i.e. in GetUtilityBeqC) RM 01/2017 
double UBeqCouples(double BequestP)
{
	double utils;
	// if (nu  ==  1.0)     // log utility OLD VERSION
	if (fabs(nu - 1.0) < ABS_TOL)     // log utility //*?#?* Now compares nearly the same 06/17 RM. Old Version above
		utils = phi2 * log(BequestP + k2);
	else
		utils = phi2 * pow(BequestP + k2, 1 - nu) / (1 - nu);
	return utils;
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// Utility from leaving bequest matrix for a single, not discounted 
/* utility from bequest for a single person
phi_j(b_net) = phi_j*( (b_net+K_j)^(1-nu) )/(1-nu) */

// lots of changes MDN 25/4/2014 eliminated intermediate step and pointer usage
//  *?#?* Replaced BequestUM with BequestUSM RM 01/2017

//  *?#?* Now accounts for end of life death costs and hew BequestUSM & scrambling of asset grid in parallelRM 08/2017
void GetUtilityBeqS(double bequestUSM[2][CASHDIM][IDIM][HSDIM][ZETADIM][CONSUMDIM], int iAssetsmin, int iAssetsmax, int* assetAssignments, int tInd)
{
	int  cashInd, cashInd2, consumInd, IInd, zetaInd, zetaIndN, xiIndN, i, hsInd, rInd; //  index 
	double temp, temp2, utils, total, income;

	double* tempvec;
	//*?#?* Updated RM 09/17 to only require one call to the MPI overhead - old missed the 2 

	int recsize = 2 * IDIM * HSDIM * ZETADIM * CASHDIM * CONSUMDIM;
	tempvec = (double*)calloc(recsize, sizeof(double));

	for (i = 0; i < 2; i++)
	{
		for (cashInd2 = iAssetsmin; cashInd2 < iAssetsmax; cashInd2++)   // COH
		{
			cashInd = assetAssignments[cashInd2]; // "Scramble" gridpoints across clusters.  JBJ:  5/30/14 *?#?* added RM 08/2017

			for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
			{


				temp = (cashS[cashInd] - consumS[consumInd]);

				//This is the correct amount of cash
				for (hsInd = 0; hsInd < HSDIM; hsInd++)
				{
					for (IInd = 0; IInd < IDIM; IInd++)
					{

						for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
						{
							total = 0.0;

							for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
							{

								for (xiIndN = 0; xiIndN < XIDIM; xiIndN++)
								{
									for (rInd = 0; rInd < RDIM; rInd++) //*?#?* added RM 05/2018 - Moved innermost (otherwise total is reset) RM 08/2018
									{
										//use the precalculated deathcosts
										// *?#?* Updated RM 09/17 to allow for dependence on lagged health loop over hsInd (today's health status entering tomorrows med cost) *?#?* Updated RM 05/2018
										//*?#?* Updated RM 06/2018. Seperated lines and allowing for taxation
										income = rA[rInd] * temp + INCDEAD * ySM[i][IInd][tInd];
										income = TAXINCDEAD * AfterTaxIncomeS(income) + (1 - TAXINCDEAD) * income;
										temp2 = temp + MODELPERIOD * income - MODELPERIOD * exp(deathcostsFinalMemberS[i][tInd][IInd][hsInd][zetaIndN][xiIndN]);
										//if (temp>=0.0) // eliminated bequest taxation OLD VERSION
										if (temp > 0.0 || fabs(temp - 0.0) < ABS_TOL) // eliminated bequest taxation /*?#?* Now compares nearly the same 06/17 RM. Old Version above
										{ //For any feasible asset values assign the constant bequest utility when death expenses wipe out their assets
											temp2 = max(temp2, 0.0);
											// if (nu  ==  1.0)     // log utility OLD VERSION
											if (fabs(nu - 1.0) < ABS_TOL)     // log utility //*?#?* Now compares nearly the same 06/17 RM. Old Version above
												utils = phi0 * log(temp2 + k0);
											else
												utils = phi0 * pow(temp2 + k0, 1 - nu) / (1 - nu);

										}
										else
										{
											utils = 0.0;
										}

										total += utils * zetaProbM[zetaInd][zetaIndN] * xiProbA[xiIndN] * rProbA[rInd]; //*?#?* Updated RM 05/2018
									} //r	

								}//xiN
							} //zetaN
							bequestUSM[i][cashInd][IInd][hsInd][zetaInd][consumInd] = total;

						} //zeta
					} //I
				}//healthstatus


			} //con


		} //cash

	}//sex
	 //*?#?* Updated RM 09/17 to only require one call to the MPI overhead
	if (useMPI == 2)
	{
		//Begin the automated commenting *?#?*- Added control sequence RM 03/17
#if(MPI_COMMENT==1)
		MPI_Allreduce(bequestUSM[0][0][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
		copyit(bequestUSM[0][0][0][0][0], tempvec, recsize);
#endif     //(MPI_COMMENT==1)
	} //Close if on MPI use
#if(MPI_COMMENT==2) //conditional compile on using openMP
#pragma omp barrier
#endif  //close on Openmp
	free(tempvec);
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// Expected utility from leaving bequest matrix for couples, not discounted 
// incorporate change to widower bequests *?#?* 08/17 RM
//incorporate change to death costs for lone survivor & scrambling of asset grid in parallel *?#?* 08/17 RM
// *?#?* Updated RM 09/17 to allow for dependence on lagged health

// *?#?* Updated RM 1/18 this section changed to seperate spouse death and final member of the household


void GetUtilityBeqHW(double bequestUHWM[CASHDIM][BEQUESTDIM], int iAssetsmin, int iAssetsmax, int* assetAssignments)
{  // Notice that bequests cannot exceed CURRENt COH-consumption 
	int cashInd, cashInd2, consumInd, bequestInd; //  index 
	double  temp;

	double* tempvec2;
	int recsize2 = CASHDIM * BEQUESTDIM; //*?#?* changed RM 11/2017 changed from CASHDIM*CONSUMDIM to CASHDIM*BEQUESTDIM which is actually correct and stops corrupting other memory

	tempvec2 = (double*)calloc(recsize2, sizeof(double));

	for (cashInd2 = iAssetsmin; cashInd2 < iAssetsmax; cashInd2++)   // COH
	{
		cashInd = assetAssignments[cashInd2]; // "Scramble" gridpoints across clusters.  JBJ:  5/30/14 *?#?* added RM 08/2017

		for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
		{

			for (bequestInd = 0; bequestInd < BEQUESTDIM; bequestInd++)
			{  // eliminate estate taxation
				temp = (bequestHWM[cashInd][bequestInd]);
				bequestUHWM[cashInd][bequestInd] = UBeqHW(temp);
			}

		}
	}


	if (useMPI == 2)
	{
		//Begin the automated commenting *?#?*- Added control sequence RM 03/17
#if(MPI_COMMENT==1)    

		MPI_Allreduce(bequestUHWM[0], tempvec2, recsize2, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
		copyit(bequestUHWM[0], tempvec2, recsize2);

#endif     //(MPI_COMMENT==1)
	} //Close if on MPI use
#if(MPI_COMMENT==2) //conditional compile on using openMP
#pragma omp barrier //wait until every processor has hit this point
#endif  //close on Openmp
	free(tempvec2);
}
// *?#?* Updated RM 1/18 this section changed to seperate spouse death and final member of the household
//Only do tind at a time
// *?#?* Updated RM 5/18 update to model equations

void GetUtilityBeqUCM(double bequestUCM[CASHDIM][IDIM][HSDIM][HSDIM][ZETADIM][CONSUMDIM], int iAssetsmin, int iAssetsmax, int* assetAssignments, int tInd)
{  // Notice that bequests cannot exceed CURRENt COH-consumption 
   //Takes tind as compute once at each time period

   /*I think I actually don't need the pragma warning here. The expectation should only exist for the cash dims
   used by a given node where I compute it for all other states and consumption choices*/
	int cashInd, cashInd2, consumInd, IInd, zetaInd, xiIndN, hsHInd, hsWInd, rInd; //  index 
	double  temp, total, temp2, utils, income;

	double* tempvec;
	int recsize = IDIM * HSDIM * HSDIM * ZETADIM * CASHDIM * CONSUMDIM;

	tempvec = (double*)calloc(recsize, sizeof(double));


	for (cashInd2 = iAssetsmin; cashInd2 < iAssetsmax; cashInd2++)   // COH
	{
		cashInd = assetAssignments[cashInd2]; // "Scramble" gridpoints across clusters.  JBJ:  5/30/14 *?#?* added RM 08/2017

		for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
		{


			temp = (cashC[cashInd] - consumC[consumInd]);

			//This is the correct amount of cash saved
			for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
			{
				for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
				{
					for (IInd = 0; IInd < IDIM; IInd++)
					{

						for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
						{
							total = 0.0;

							for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
							{

								for (xiIndN = 0; xiIndN < XIDIM; xiIndN++)
								{
									for (rInd = 0; rInd < RDIM; rInd++) //*?#?* added RM 05/2018 added RM 05/2018 - Moved innermost (otherwise total is reset) RM 08/2018
									{
										//use the precalculated deathcosts *?#?* Updated RM 05/2018
										//*?#?* Updated RM 06/2018. Seperated lines and allowing for taxation
										income = rA[rInd] * temp + INCDEAD * yCM[IInd][tInd];
										income = TAXINCDEAD * AfterTaxIncomeC(income) + (1 - TAXINCDEAD) * income;
										temp2 = temp + rA[rInd] * temp + MODELPERIOD * income - MODELPERIOD * exp(deathcostsFinalMemberC[tInd][IInd][hsHInd][hsWInd][zetaIndN][xiIndN]);
										//if (temp>=0.0) // eliminated bequest taxation OLD VERSION
										if (temp > 0.0 || fabs(temp - 0.0) < ABS_TOL) // eliminated bequest taxation /*?#?* Now compares nearly the same 06/17 RM. Old Version above
										{//For any feasible asset values assign the constant bequest utility when death expenses wipe out their assets
											temp2 = max(temp2, 0.0);

											utils = UBeqCouples(temp2);
										}
										else
										{
											utils = 0.0;
										}

										total += utils * zetaProbM[zetaInd][zetaIndN] * xiProbA[xiIndN] * rProbA[rInd]; //*?#?* Updated RM 05/2018

									} //r	
								}//xiN
							} //zetaN
							bequestUCM[cashInd][IInd][hsHInd][hsWInd][zetaInd][consumInd] = total;

						} //zeta
					} //I
				}//Husband Health
			}//Wife health
		} //con
	} //cash
	if (useMPI == 2)
	{
		//Begin the automated commenting *?#?*- Added control sequence RM 03/17
#if(MPI_COMMENT==1)
		MPI_Allreduce(bequestUCM[0][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
		copyit(bequestUCM[0][0][0][0][0], tempvec, recsize);

#endif     //(MPI_COMMENT==1)
	} //Close if on MPI use
#if(MPI_COMMENT==2) //conditional compile on using openMP
#pragma omp barrier //wait until every processor has hit this point
#endif  //close on Openmp
	free(tempvec);
}

// *?#?* old below: 08/17 RM
/*
void GetUtilityBeqC(double bequestUCM[CASHDIM][CONSUMDIM],double bequestUHWM[CASHDIM][CONSUMDIM][BEQUESTDIM])
{  // Notice that bequests cannot exceed CURRENt COH-consumption
int cashInd, consumInd, bequestInd; //  index
double  temp;

for (cashInd = 0; cashInd<CASHDIM; cashInd++)
{
for (consumInd = 0; consumInd<CONSUMDIM; consumInd++)
{
// both die
temp = (cashC[cashInd]-consumC[consumInd]); // bequest
//if (temp>=0.0) // eliminated bequest taxation OLD VERSION
if (temp>0.0|| fabs(temp-0.0)<ABS_TOL) // eliminated bequest taxation /*?#?* Now compares nearly the same 06/17 RM. Old Version above
{
bequestUCM[cashInd][consumInd]=UBeqCouples(temp);

// Only one dies
for (bequestInd = 0; bequestInd<BEQUESTDIM; bequestInd++)
{  // eliminate estate taxation
temp = (bequestHWM[cashInd][consumInd][bequestInd]);
bequestUHWM[cashInd][consumInd][bequestInd]=UBeqHW(temp);
}
}
else break;
}
}
}
*/

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/*Tax functions based on the Guner et al. estimates (2012)
*?#?* Added RM 03/2017*/
double AfterTaxIncomeS(double y)
{
	double tax;
	if (y < 0.0)
	{
		// printf("Error! negtive gross income!\n "); 
		return -1;  // this case will be ruled out in maximization  
	}
	else
	{

		tax = tax_b1 - tax_b1 * pow((tax_s1 * pow(y, tax_p1) + 1), -1.0 / tax_p1);
		return y - tax * y;
	}
}

double AfterTaxIncomeC(double y)
{
	double tax;
	if (y < 0.0)
	{
		// printf("Error! negtive gross income!\n "); 
		return -1;  // this case will be ruled out in maximization  
	}
	else
	{

		tax = tax_b0 - tax_b0 * pow((tax_s0 * pow(y, tax_p0) + 1), -1.0 / tax_p0);
		return y - tax * y;
	}
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/*  Locates nearest point in an array
From Numerical Recipes in C, p. 117
*/

int Locate(double* Xarray, double x, int DIM)
{
	int j_L, j_U, j_M, ascend, dif, j_Star;

	ascend = 1;
	if (Xarray[DIM - 1] < Xarray[0]) ascend = 0;

	j_L = 0;
	j_U = DIM - 1;
	dif = j_U - j_L;

	if (ascend == 1)
	{
		while (dif > 1)
		{
			j_M = (int)(j_U + j_L) / 2;
			if (x > Xarray[j_M])
				j_L = j_M;
			else
				j_U = j_M;

			dif = j_U - j_L;
		}
		j_Star = j_L;
	}

	else
	{
		while (dif > 1)
		{
			j_M = (int)(j_U + j_L) / 2;
			if (x < Xarray[j_M])
				j_L = j_M;
			else
				j_U = j_M;
			dif = j_U - j_L;
		}
		j_Star = j_L;
	}

	return j_Star;
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// Returns linearly interpolated or extrapolated value at x 

double Interpolation(double* fP, double* xP, double x, int DIM)
{
	int j;

	j = Locate(xP, x, DIM) + 1;
	return (x - *(xP + j)) * (*(fP + j - 1) - *(fP + j)) / (*(xP + j - 1) - *(xP + j)) + (*(fP + j));  //x[j-1]<x<x[j] 
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// Returns grid point and linear interpolation weight 
struct result GetLocation(double* xP, double x, int DIM)
{
	int j;
	struct result result1;

	j = Locate(xP, x, DIM) + 1;
	result1.Ind1 = j - 1;
	result1.weight = (*(xP + j) - x) / (*(xP + j) - *(xP + j - 1));
	return result1;
}

// *?#?* Added to pass control of zeta/xi dimensionality to gauss 08/2017 RM


//From AER paper code:
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/*  markovChnderef:  Deferences values and probabilities for persistent shocks.   */
/*                   Also returns the invariant probability vector                */

int markovChnderef(double* zetavecPtr, int trueDim, double rho, double sigma_zeta,
	double* zetaA, double* zetaMatrixP, double* zetaInvarV)
{
	int zetaDim2, iZeta, rowNum, iRow;

	zetaDim2 = (int)floor(rounder + zetavecPtr[0]);

	// trueDim is the dimension hardwired in the C code, may not match what is read in

	if (zetaDim2 == trueDim)
	{
		if (rho == 0) rowNum = 1;    /* iid process  */
		else rowNum = trueDim;       /* AR(1) process  */

		for (iZeta = 0; iZeta < trueDim; iZeta++)
			zetaA[iZeta] = (zetavecPtr[1 + iZeta]) * sigma_zeta;

		for (iRow = 0; iRow < rowNum; iRow++)
		{
			for (iZeta = 0; iZeta < trueDim; iZeta++)
				*(zetaMatrixP + iRow * trueDim + iZeta) = zetavecPtr[trueDim + 1 + iRow * trueDim + iZeta];
		}

		/* Find stationary distribution using brute force, by repeatedly multiplying Pi by itself */

		if (rowNum == 1)
		{
			for (iZeta = 0; iZeta < trueDim; iZeta++)
				zetaInvarV[iZeta] = zetavecPtr[trueDim + 1 + iZeta];
		}
		else
		{
			getInvar(trueDim, zetaMatrixP, zetaInvarV);
		}

	}
	else
	{
		printf("Error! Transitory Shock dimensions don't match!\n ");
		fflush(stdout);
	}

	return zetaDim2;
}
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/*  GETINVAR:  Find invariant distribution of Markov Chain by brute force, by     */
/*             by repeatedly multiplying Pi by itself                             */
/*             JBJ:  9/18/08, 07/13/14                                            */

void getInvar(int n, double* piMatrixP, double* piInvarV)
{
	double** ProductMat, ** subtot;
	int h, i, j, k;  /* indices */

	ProductMat = (double**)malloc(n * sizeof(double*));
	subtot = (double**)malloc(n * sizeof(double*));

	for (i = 0; i < n; i++)
	{
		ProductMat[i] = (double*)malloc(n * sizeof(double));
		subtot[i] = (double*)calloc(n, sizeof(double));
		for (j = 0; j < n; j++)
			ProductMat[i][j] = *(piMatrixP + i * n + j);
	}

	for (h = 0; h < 2000; h++)
	{
		for (i = 0; i < n; i++)
		{
			for (j = 0; j < n; j++)
			{
				subtot[i][j] = 0;
				for (k = 0; k < n; k++)
					subtot[i][j] += ProductMat[i][k] * (*(piMatrixP + k * n + j));
			}
		}

		for (i = 0; i < n; i++)
		{
			for (j = 0; j < n; j++)
				ProductMat[i][j] = subtot[i][j];
		}
	}

	for (i = 0; i < n; i++)
		piInvarV[i] = ProductMat[0][i];
	//Added RM 11/17 *?#?* 
	for (i = 0; i < n; i++)
	{
		free(ProductMat[i]);
		free(subtot[i]);
	}

	free(subtot);
	free(ProductMat);
}

/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/* Revised by JBJ:  9/18/08 */

void GetCdf(int nRows, int nCols, double* piMatrixP, double* piMatrixCDF)
{
	int iRow, iCol;
	double sum;

	for (iRow = 0; iRow < nRows; iRow++)
	{
		sum = 0;
		for (iCol = 0; iCol < nCols + 1; iCol++)
		{
			*(piMatrixCDF + iRow * (nCols + 1) + iCol) = sum;
			sum += *(piMatrixP + iRow * nCols + iCol);
		}
	}
	return;
}
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/*
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// Revised by JBJ:  7/11/08

void GetCdf(int nRows, int nCols, double *piMatrixP, double *piMatrixCDF)
{
int iRow, iCol;
double sum;

for (iRow=0; iRow<nRows; iRow++)
{
sum = 0;
for (iCol=0; iCol<nCols+1; iCol++)
{
*(piMatrixCDF + iRow*(nCols+1) + iCol) = sum;
sum += *(piMatrixP + iRow*nCols + iCol);
}
}
return;
}
*/
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

void WriteData(double** assetsimMat, double** netIncomesimMat, double** consumptionsimMat,
	double** healthcostsimMat, double** zetaindexsimMat, double** marstatsimMat,
	GMatrix agesim96Ptr, GMatrix PIsim96Ptr, double** healthsimhMat,
	double** healthsimwMat)
{
	int i, tInd, IInd, hsInd, hsIndN;
	int hsHInd, hsWInd, hsHIndN, hsWIndN;
	int yearInd, personInd;
	char fullpath[ADDRESS_LEN];

	FILE* fp;

	FILE* valueFP;         // point to files related to singles case 
	FILE* consumFP;
	FILE* beqFP;
	int zetaInd, cashInd;

	FILE* valueFCP;       // point to files related to couples case 
	FILE* consumFCP;
	FILE* bequestFHP;    // point to  bequest file related to the case when husband dies first 
	FILE* bequestFWP;    // point to bequest  related to the case when wife dies first 
	FILE* bequestFCP;    // both die 
						 //*?#?* Changed to singles incprofS1 and <2 not <3 RM 01/2017
	fp = fopen(strcat(strcpy(fullpath, outputdir), "incprofS1.txt"), "w");

	for (i = 0; i < 2; i++) //Output forsingles
	{
		for (IInd = 0; IInd < IDIM; IInd++)
		{
			for (tInd = 0; tInd < TDIMS + 1; tInd++)   //JJJJJJJ  time reordered to be column dimension 
			{
				fprintf(fp, "%20.8lf", ySM[i][IInd][tInd]);
			}
			fprintf(fp, "\n");
		}
	}

	fclose(fp);

	//-------------------------------------------------------------------------------

	fp = fopen(strcat(strcpy(fullpath, outputdir), "survivalProS1.txt"), "w"); // open file

	for (i = 0; i < 2; i++)
	{
		for (hsInd = 0; hsInd < HSDIM; hsInd++)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (tInd = 0; tInd < TDIMS; tInd++)   // JJJJJJJ  time reordered to be column dimension 
				{
					fprintf(fp, "%20.8lf", survivalProbSM[i][tInd][hsInd][IInd]);
				}
				fprintf(fp, "\n");
			}
		}
	}
	fclose(fp);

	//--------------------------------------------------------------------------------
	//  double hsProbSM[2][TDIMS][IDIM][HSDIM][HSDIM];  // Singles 
	//*?#?* hsTransitionS1 from profheal1 RM 01/2017

	fp = fopen(strcat(strcpy(fullpath, outputdir), "hsTransitionS1.txt"), "w");

	for (i = 0; i < 2; i++)
	{
		for (hsInd = 0; hsInd < HSDIM; hsInd++)
		{
			for (hsIndN = 0; hsIndN < HSDIM; hsIndN++)
			{
				for (IInd = 0; IInd < IDIM; IInd++)
				{
					for (tInd = 0; tInd < TDIMS; tInd++)   //JJJJJJJ  time reordered to be column dimension 
					{
						fprintf(fp, "%20.8lf", hsProbSM[i][tInd][IInd][hsInd][hsIndN]);
					}
					fprintf(fp, "\n");
				}
			}
		}
	}

	fclose(fp);

	//--------------------------------------------------------------------------------


	if (switchCouple == 1)
	{
		//*?#?* Added due to splitting of income process RM 01/2017
		fp = fopen(strcat(strcpy(fullpath, outputdir), "incprofC1.txt"), "w");


		for (IInd = 0; IInd < IDIM; IInd++) //Output for couples
		{
			for (tInd = 0; tInd < TDIMC + 1; tInd++)   //JJJJJJJ  time reordered to be column dimension 
			{
				fprintf(fp, "%20.8lf", yCM[IInd][tInd]);
			}
			fprintf(fp, "\n");
		}

		fclose(fp);

		//-------------------------------------------------------------------------------
		// health status transition matrix for couples 
		// double hsProbCM[2][TDIMC][IDIM][HSDIM][HSDIM];  // Couples

		fp = fopen(strcat(strcpy(fullpath, outputdir), "hsTransitionC1.txt"), "w");
		for (i = 0; i < 2; i++)
		{
			for (hsInd = 0; hsInd < HSDIM; hsInd++)
			{
				for (hsIndN = 0; hsIndN < HSDIM; hsIndN++)
				{
					for (IInd = 0; IInd < IDIM; IInd++)
					{
						for (tInd = 0; tInd < TDIMC; tInd++)   //JJJJJJJ  time reordered to be column dimension 
						{
							fprintf(fp, "%20.8lf", hsProbCM[i][tInd][IInd][hsInd][hsIndN]);
						}
						fprintf(fp, "\n");
					}
				}
			}
		}

		fclose(fp);

		//-------------------------------------------------------------------------------

		fp = fopen(strcat(strcpy(fullpath, outputdir), "hcInterceptC1.txt"), "w");
		for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
		{
			for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
			{
				for (hsHIndN = 0; hsHIndN < HSDIM; hsHIndN++)
				{
					for (hsWIndN = 0; hsWIndN < HSDIM; hsWIndN++)
					{
						for (IInd = 0; IInd < IDIM; IInd++)
						{
							for (tInd = 0; tInd < TDIMC + 1; tInd++)   //JJJJJJJ  time reordered to be column dimension  
							{
								fprintf(fp, "%20.8lf", hcCIntercept[hsHInd][hsHIndN][hsWInd][hsWIndN][tInd][IInd]);
							}
							fprintf(fp, "\n");
						}
					}
				}
			}
		}
		fclose(fp);

		//-------------------------------------------------------------------------------

		fp = fopen(strcat(strcpy(fullpath, outputdir), "hcsigmaC1.txt"), "w");
		for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
		{
			for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
			{
				for (hsHIndN = 0; hsHIndN < HSDIM; hsHIndN++)
				{
					for (hsWIndN = 0; hsWIndN < HSDIM; hsWIndN++)
					{
						for (IInd = 0; IInd < IDIM; IInd++)
						{
							for (tInd = 0; tInd < TDIMC + 1; tInd++)   //JJJJJJJ  time reordered to be column dimension 
							{
								fprintf(fp, "%10.2lf", hcCSigma[hsHInd][hsHIndN][hsWInd][hsWIndN][tInd][IInd]);
							}
							fprintf(fp, "\n");
						}

					}
				}
			}
		}
		fclose(fp);


		//-------------------------------------------------------------------------------
		// survival probability matrix for couples 
		//    double survivalProbCM[2][TDIMC][HSDIM][IDIM];

		fp = fopen(strcat(strcpy(fullpath, outputdir), "survivalProC1.txt"), "w"); // open file

		for (i = 0; i < 2; i++)
		{
			for (hsInd = 0; hsInd < HSDIM; hsInd++)
			{
				for (IInd = 0; IInd < IDIM; IInd++)
				{
					for (tInd = 0; tInd < TDIMC; tInd++)   // JJJJJJJ  time reordered to be column dimension 
					{
						fprintf(fp, "%20.8lf", survivalProbCM[i][tInd][hsInd][IInd]);
					}
					fprintf(fp, "\n");
				}
			}
		}
		fclose(fp);

		//--------------------------------------------------------------------------------


	} //if (switchCouple==1)

	  //--------------------------------------------------------------------------------

	  //*?#?* hcinterceptS1.txt from hcSintercept1.txt RM 01/2017
	fp = fopen(strcat(strcpy(fullpath, outputdir), "hcInterceptS1.txt"), "w");
	for (i = 0; i < 2; i++)
	{
		for (hsInd = 0; hsInd < HSDIM; hsInd++)
		{
			for (hsIndN = 0; hsIndN < HSDIM; hsIndN++)
			{
				for (IInd = 0; IInd < IDIM; IInd++)
				{
					for (tInd = 0; tInd < TDIMS + 1; tInd++)   //JJJJJJJ  time reordered to be column dimension 
					{
						fprintf(fp, "%20.8lf", hcSIntercept[i][hsInd][hsIndN][tInd][IInd]);
					}
					fprintf(fp, "\n");
				}
			}
		}
	}
	fclose(fp);
	//*?#?* hcsigmaS1.txt from hcSsigma1.txt RM 01/2017
	fp = fopen(strcat(strcpy(fullpath, outputdir), "hcsigmaS1.txt"), "w");
	for (i = 0; i < 2; i++)
	{
		for (hsInd = 0; hsInd < HSDIM; hsInd++)
		{
			for (hsIndN = 0; hsIndN < HSDIM; hsIndN++)
			{
				for (IInd = 0; IInd < IDIM; IInd++)
				{
					for (tInd = 0; tInd < TDIMS + 1; tInd++)   //JJJJJJJ  time reordered to be column dimension 
					{
						fprintf(fp, "%20.8lf", hcSSigma[i][hsInd][hsIndN][tInd][IInd]);
					}
					fprintf(fp, "\n");
				}
			}
		}
	}
	fclose(fp);

	// value and policy functions Couples case
	//*?#?* Added a condition on couples switch RM 01/2017

	if (switchCouple == 1)
	{
		valueFCP = fopen(strcat(strcpy(fullpath, outputdir), "valueFC.txt"), "w");  // value function 
		consumFCP = fopen(strcat(strcpy(fullpath, outputdir), "consumptionFC.txt"), "w");  // consumption policy function  
		bequestFCP = fopen(strcat(strcpy(fullpath, outputdir), "bequestFC.txt"), "w"); //Savings rule
																					   //*?#?* Edited the loop to remove WIFEAGEDIF RM 01/2017
																					   // OLD: for (tInd = (TDIMC-WIFEAGEDIF-1); tInd>= 0; tInd--)

		for (tInd = (TDIMC - 1); tInd >= 0; tInd--)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
				{
					for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
					{
						for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
						{
							for (cashInd = 0; cashInd < CASHDIM; cashInd++)
							{
								// write value function and policy function to files 
								fprintf(valueFCP, "%12.20f  ", valueFunCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd]); // *?#?* RM 06/2017 changed format as Decimal places too low
								fprintf(consumFCP, "%12.4f  ", consumFunCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd]);

								fprintf(bequestFCP, "%12.4f  ", bequestFunCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd]);
							} // end loop through cash on hand  
							fprintf(valueFCP, "\n");
							fprintf(consumFCP, "\n");
							fprintf(bequestFCP, "\n");
						} // end loop through persistent health shock 
						fprintf(valueFCP, "\n");
						fprintf(consumFCP, "\n");
						fprintf(bequestFCP, "\n");
					}// end loop through health status for wife  
				}// end loop through health status for husband 
			}   // end loop through permanent income    
		} // end loop through age 

		  //Moved RM 11/17 RM #?*?#
		  //End writing to files
		fclose(valueFCP);
		fclose(consumFCP);
		fclose(bequestFCP);

		bequestFWP = fopen(strcat(strcpy(fullpath, outputdir), "bequestFW.txt"), "w");
		bequestFHP = fopen(strcat(strcpy(fullpath, outputdir), "bequestFH.txt"), "w");


		for (tInd = (TDIMC - 1); tInd >= 0; tInd--)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (hsInd = 0; hsInd < HSDIM; hsInd++)
				{

					for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
					{
						for (cashInd = 0; cashInd < CASHDIM; cashInd++)
						{


							fprintf(bequestFHP, "%12.4f  ", bequestFunHM[tInd][IInd][hsInd][zetaInd][cashInd]);
							fprintf(bequestFWP, "%12.4f  ", bequestFunWM[tInd][IInd][hsInd][zetaInd][cashInd]);

						} // end loop through cash on hand  
						fprintf(bequestFHP, "\n");
						fprintf(bequestFWP, "\n");

					} // end loop through persistent health shock 
					fprintf(bequestFHP, "\n");
					fprintf(bequestFWP, "\n");

				}// end loop through health status for husband

			}   // end loop through permanent income    
		} // end loop through age 

		  // End writing to files 
		fclose(bequestFWP);
		fclose(bequestFHP);

	} //if (switchCouple==1)

	  //--------------------------------------------------------------------------------

	valueFP = fopen(strcat(strcpy(fullpath, outputdir), "valueF.txt"), "w");  // value function 
	consumFP = fopen(strcat(strcpy(fullpath, outputdir), "consumptionF.txt"), "w");  // consumption policy function 
	beqFP = fopen(strcat(strcpy(fullpath, outputdir), "bequestFS.txt"), "w");  // bequest policy function 

																			   // *?#?* Renamed as bequest FS to avoid inconsistency RM 01/2017. OLD:
																			   //beqFP    = fopen(strcat(strcpy(fullpath,outputdir),"bequestSF.txt"),"w");  // bequest policy function 

																			   // Print value function for t = 1, ..., T  where value function for T+1 is defined as 0 matrix 
																			   // single case 
	for (i = 0; i < 2; i++)
	{
		for (tInd = (TDIMS - 1); tInd >= 0; tInd--)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (hsInd = 0; hsInd < HSDIM; hsInd++)
				{
					for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
					{
						for (cashInd = 0; cashInd < CASHDIM; cashInd++)
						{
							// write value function and policy function to files 
							fprintf(valueFP, "%12.20f  ", valueFunSM[i][tInd][IInd][hsInd][zetaInd][cashInd]);
							fprintf(consumFP, "%12.4f  ", consumFunSM[i][tInd][IInd][hsInd][zetaInd][cashInd]);
							fprintf(beqFP, "%12.4f  ", bequestFunSM[i][tInd][IInd][hsInd][zetaInd][cashInd]);
							// *?#?* replaced BequestFunSSM with bequestFunSM as previous identifier not defined RM 01/2017
						}

						fprintf(valueFP, "\n");
						fprintf(consumFP, "\n");
						fprintf(beqFP, "\n");
					}

					fprintf(valueFP, "\n");
					fprintf(consumFP, "\n");
					fprintf(beqFP, "\n");
				}// end loop through health status 
			} // end loop through permanent income    
		} // end loop through age 
	} // end loop through sex 

	  // End writing to files  
	fclose(valueFP);
	fclose(consumFP);
	fclose(beqFP);

	//--------------------------------------------------------------------------------
	// simulation results 

	fp = fopen(strcat(strcpy(fullpath, outputdir), "zetaindsimMat.txt"), "w");
	for (personInd = 0; personInd < nsims; personInd++)
	{
		for (yearInd = 0; yearInd < TDimSims; yearInd++)  // calendar year 
		{
			fprintf(fp, "%10.1lf", zetaindexsimMat[yearInd][personInd]);
		}
		fprintf(fp, "\n");
	}
	fclose(fp);


	fp = fopen(strcat(strcpy(fullpath, outputdir), "assetsimMat.txt"), "w");
	for (personInd = 0; personInd < nsims; personInd++)
	{
		for (yearInd = 0; yearInd < TDimSims + 1; yearInd++)  // calendar year
		{
			fprintf(fp, "%20.3lf", assetsimMat[yearInd][personInd]);
		}
		fprintf(fp, "\n");
	}
	fclose(fp);

	fp = fopen(strcat(strcpy(fullpath, outputdir), "consumptionsimMat.txt"), "w");
	for (personInd = 0; personInd < nsims; personInd++)
	{

		for (yearInd = 0; yearInd < TDimSims + 1; yearInd++)  // calendar year 
		{
			fprintf(fp, "%20.3lf", consumptionsimMat[yearInd][personInd]);
		}
		fprintf(fp, "\n");
	}
	fclose(fp);

	fp = fopen(strcat(strcpy(fullpath, outputdir), "healthcostsimMat.txt"), "w");
	for (personInd = 0; personInd < nsims; personInd++)
	{
		for (yearInd = 0; yearInd < TDimSims + 1; yearInd++)  // calendar year 
		{
			fprintf(fp, "%20.5lf", healthcostsimMat[yearInd][personInd]);
		}
		fprintf(fp, "\n");
	}
	fclose(fp);


	fp = fopen(strcat(strcpy(fullpath, outputdir), "marstatsimMat.txt"), "w");
	for (personInd = 0; personInd < nsims; personInd++)
	{
		for (yearInd = 0; yearInd < TDimSims; yearInd++)
		{
			fprintf(fp, "%20.5lf", marstatsimMat[yearInd][personInd]);
		}
		fprintf(fp, "\n");
	}
	fclose(fp);


	fp = fopen(strcat(strcpy(fullpath, outputdir), "PI94.txt"), "w");

	for (personInd = 0; personInd < nsims; personInd++)
	{
		fprintf(fp, "%10.5lf", PIsim96Ptr.data[personInd]);
		fprintf(fp, "\n");

	}
	fclose(fp);
	// *?#?* Changed from age94.txt to age96.txt RM 01/2017
	fp = fopen(strcat(strcpy(fullpath, outputdir), "age96.txt"), "w");

	for (personInd = 0; personInd < nsims; personInd++)
	{
		fprintf(fp, "%10.5lf", agesim96Ptr.data[personInd]);
		fprintf(fp, "\n");

	}
	fclose(fp);


	fp = fopen(strcat(strcpy(fullpath, outputdir), "healthsimhMat.txt"), "w");
	for (personInd = 0; personInd < nsims; personInd++)
	{
		for (yearInd = 0; yearInd < TDimSims; yearInd++)  //calendar year 
		{
			fprintf(fp, "%20.5lf", healthsimhMat[yearInd][personInd]);
		}
		fprintf(fp, "\n");
	}
	fclose(fp);


	fp = fopen(strcat(strcpy(fullpath, outputdir), "healthsimwMat.txt"), "w");
	for (personInd = 0; personInd < nsims; personInd++)
	{
		for (yearInd = 0; yearInd < TDimSims; yearInd++)  //calendar year 
		{
			fprintf(fp, "%20.5lf", healthsimwMat[yearInd][personInd]);
		}
		fprintf(fp, "\n");
	}
	fclose(fp);


	fp = fopen(strcat(strcpy(fullpath, outputdir), "NetIncomeSimMat.txt"), "w");
	for (personInd = 0; personInd < nsims; personInd++)
	{
		for (yearInd = 0; yearInd < TDimSims + 1; yearInd++)  // calendar year 
		{
			fprintf(fp, "%20.5lf", netIncomesimMat[yearInd][personInd]);
		}
		fprintf(fp, "\n");
	}
	fclose(fp);

}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//==== *?#?* Modified by 05/2017 RM to account for multiple health states (LTC) & couples
//*?#?* Modified by RM 06/2017 to update I/O in line with GAUSS & on 08/17 to add death costs
//  based on 01/2017 RM (based on 08  by JBJ) and incorporating vectors of coefficieicnts as in JBJ: 1/27/12   ====
// *?#?* Modified by RM 10/2022 to include no risk case for singles
int GetProfilesNEW(double* agevecPtr,
	double* hstrans_coeffsPtr, double* lnhc_meanPtr, double* lnhc_varPtr, double* lnhc_mean_noriskPtr, double* lnhc_var_noriskPtr,
	double* yprofPtr, double* yprofPIPtr)
{
	int i, j, sexInd, tInd, IInd, hsInd, hsInd2, hsHInd, hsHInd2, hsWInd2, hsWInd, tdimGAUSS, tdimCGAUSS;

	double income, ageD, PI1, PI2, PI3, PI4, PI5,
		PIC1, PIC2, PIC3, PIC4, PIC5;

	double HSProbs[HSDIM];
	double** hsCoeffs;

	tdimGAUSS = (int)floor(rounder + agevecPtr[4]);
	tdimCGAUSS = tdimGAUSS; //(int) floor(rounder+agevecPtr[4]);

	if (tdimGAUSS != TDIMS)
	{
		printf("Incompatible timespans for singles!!! \n");
		fflush(stdout);

	}


	if (tdimCGAUSS != TDIMC)
	{
		printf("Incompatible timespans for couples!!! \n");
		fflush(stdout);
	}


	// Income 
	/*For singles (assume that the men have coefficients even when they are dead
	so that the ordering of the vector doesn't change. Assume also that the vector
	cycles through all of the singles and has couples stacked after. */
	j = 0;
	i = 0;

	//Note: Latest version we have 5th order polynomial in PI
	for (tInd = 0; tInd < TDIMC; tInd++) //Loop through the couple values and then fill the addiional singles later
	{
		for (sexInd = 0; sexInd < 2; sexInd++) // Single male, single female   
		{
			income = yprofPtr[i];
			PIC1 = yprofPIPtr[j];
			PIC2 = yprofPIPtr[j + 1];
			PIC3 = yprofPIPtr[j + 2];
			PIC4 = yprofPIPtr[j + 3];
			PIC5 = yprofPIPtr[j + 4];

			i++;
			j += 5;
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				PI1 = IncomeA[IInd];
				PI2 = pow(PI1, 2);
				PI3 = pow(PI1, 3);
				PI4 = pow(PI1, 4);
				PI5 = pow(PI1, 5);
				ySM[sexInd][IInd][tInd] = exp(income + PIC1 * PI1 + PIC2 * PI2 + PIC3 * PI3 + PIC4 * PI4 + PIC5 * PI5);
			}


		}

		//just as before, but now indexes only jump once with each time period
		income = yprofPtr[i];
		PIC1 = yprofPIPtr[j];
		PIC2 = yprofPIPtr[j + 1];
		PIC3 = yprofPIPtr[j + 2];
		PIC4 = yprofPIPtr[j + 3];
		PIC5 = yprofPIPtr[j + 4];

		i++;
		j += 5;

		for (IInd = 0; IInd < IDIM; IInd++)
		{
			PI1 = IncomeA[IInd];
			PI2 = pow(PI1, 2);
			PI3 = pow(PI1, 3);
			PI4 = pow(PI1, 4);
			PI5 = pow(PI1, 5);
			yCM[IInd][tInd] = exp(income + PIC1 * PI1 + PIC2 * PI2 + PIC3 * PI3 + PIC4 * PI4 + PIC5 * PI5);
		}
	}
	//as it goes men first we need to move on i & j- because on the last pass through we already skip on beyond
	// women's intercept and mean
	i++; //Skip the man's value
	j += 2; //Skip the man's coefficients
	for (tInd = TDIMC; tInd < TDIMS; tInd++) //Loop through the couple values and then fill the addiional singles later
	{

		income = yprofPtr[i];
		PIC1 = yprofPIPtr[j];
		PIC2 = yprofPIPtr[j + 1];
		PIC3 = yprofPIPtr[j + 2];
		PIC4 = yprofPIPtr[j + 3];
		PIC5 = yprofPIPtr[j + 4];

		i += 3; //Skip to the next single woman (because M,W,C)
		j += 15; //Don't need the male indexes because will all be set to zero
		for (IInd = 0; IInd < IDIM; IInd++)
		{
			PI1 = IncomeA[IInd];
			PI2 = pow(PI1, 2);
			PI3 = pow(PI1, 3);
			PI4 = pow(PI1, 4);
			PI5 = pow(PI1, 5);
			ySM[1][IInd][tInd] = exp(income + PIC1 * PI1 + PIC2 * PI2 + PIC3 * PI3 + PIC4 * PI4 + PIC5 * PI5);
			ySM[0][IInd][tInd] = 0.0000; // Men are dead
		}


	}
	// WIll fill in place holders later




	// Health Status transition probabilities for singles 
	// Health expense parameters for singles 
	// Survival Probabilities for singles 




	//* Demographic Transitions {NH,Bad,Good} -> {dead,NY,Bad,Good} modelled using MV Logit */
	//* These will be transformed into P(alive|X)*P(health|alive,X) */
	//* First, load up the underlying coefficients */
	//* JBJ: 1/27/12 */
	//* Modified by RM for couples 15/05/17 */   

	hsCoeffs = (double**)malloc((HSDIM) * sizeof(double*)); // MV Logit coefficients 

															  //*?#?* removed the placeholder values for healthcosts (as backwards looking and now in final member death costs) 08/17 RM


	for (hsInd = 0; hsInd < HSDIM; hsInd++)
		hsCoeffs[hsInd] = &hstrans_coeffsPtr[hsInd * COEFFNUM];  // Input from GAUSS ordered by health status, coefficient


															   //*?#?* Dimension is changed here 08/17 RM
															   //*?#?* Dimension is reverted here -major bounds overrun issue (noticed on MS compiler) 10/17 RM

	for (tInd = 0; tInd < TDIMC; tInd++)
	{

		ageD = (double)(tInd * MODELPERIOD + TSTART);
		for (sexInd = 0; sexInd < 2; sexInd++)
		{

			for (IInd = 0; IInd < IDIM; IInd++)
			{
				PI1 = IncomeA[IInd];



				for (hsInd = 0; hsInd < HSDIM; hsInd++)  //  LTC, bad, then good, 
				{
					//Singles first
					survivalProbSM[sexInd][tInd][hsInd][IInd] =
						GetTransProbs(hsCoeffs, ageD, sexInd, PI1, hsInd, HSProbs, 0);
					for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)  // Future health
						hsProbSM[sexInd][tInd][IInd][hsInd][hsInd2] = HSProbs[hsInd2];
					/* XtimesBeta_HCOST(double *coeffs, double age, int sexInd, double PInc,int laghealthStatH,
					int laghealthStatW, int healthStatH, int healthStatW, int couplestatus)
					Below I duplicate hsind and hsind2 to pass the same arguments for men and women, only one of these will be used
					as the couple status is always set to 0*/

					for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)  // Current  health so that hsind is lagged
					{
						hcSIntercept[sexInd][hsInd][hsInd2][tInd][IInd] =
							XtimesBeta_HCOST(lnhc_meanPtr, ageD, sexInd, PI1, hsInd, hsInd, hsInd2, hsInd2, 0);
						hcSSigma[sexInd][hsInd][hsInd2][tInd][IInd] =
							sqrt(XtimesBeta_HCOST(lnhc_varPtr, ageD, sexInd, PI1, hsInd, hsInd, hsInd2, hsInd2, 0));
					}
					//Couples
					survivalProbCM[sexInd][tInd][hsInd][IInd] =
						GetTransProbs(hsCoeffs, ageD, sexInd, PI1, hsInd, HSProbs, 1);
					for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)  // Future health
						hsProbCM[sexInd][tInd][IInd][hsInd][hsInd2] = HSProbs[hsInd2];

				}




			}

		} //Close on sex

		  // Fill in couples Intercepts and variances for health costs

		  //Select coefficients in the same way as singles

		for (IInd = 0; IInd < IDIM; IInd++)
		{
			PI1 = IncomeA[IInd];

			for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)  /* Husband's health*/
			{
				for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)  /* Wife's health */
				{


					for (hsHInd2 = 0; hsHInd2 < HSDIM; hsHInd2++)  // Current  health so that hsind is lagged
					{  //Malestatus is used only for singles as we evaluaate at the couple level
						for (hsWInd2 = 0; hsWInd2 < HSDIM; hsWInd2++)  // Current  health so that hsind is lagged
						{
							hcCIntercept[hsHInd][hsHInd2][hsWInd][hsWInd2][tInd][IInd] = XtimesBeta_HCOST(lnhc_meanPtr, ageD, 0, PI1, hsHInd, hsWInd, hsHInd2, hsWInd2, 1);
							hcCSigma[hsHInd][hsHInd2][hsWInd][hsWInd2][tInd][IInd] = sqrt(XtimesBeta_HCOST(lnhc_varPtr, ageD, 0, PI1, hsHInd, hsWInd, hsHInd2, hsWInd2, 1));
						}
					}
				}
			}
		} //Close on PI


	} // Close on age
	  //After the final age period health costs (which will always be used combined with death costs). Note 0 indexing means this is TDIMC+1 periods
	  //*?#?*  10/17 RM

	tInd = TDIMC;
	ageD = (double)(tInd * MODELPERIOD + TSTART);
	sexInd = 0;
	//COuple values & single men
	for (IInd = 0; IInd < IDIM; IInd++)
	{
		PI1 = IncomeA[IInd];

		for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)  /* Husband's health*/
		{
			for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)  /* Wife's health */
			{


				for (hsHInd2 = 0; hsHInd2 < HSDIM; hsHInd2++)  // Current  health so that hsind is lagged
				{  //Malestatus is used only for singles as we evaluaate at the couple level
					for (hsWInd2 = 0; hsWInd2 < HSDIM; hsWInd2++)  // Current  health so that hsind is lagged
					{
						hcCIntercept[hsHInd][hsHInd2][hsWInd][hsWInd2][tInd][IInd] = XtimesBeta_HCOST(lnhc_meanPtr, ageD, 0, PI1, hsHInd, hsWInd, hsHInd2, hsWInd2, 1);
						hcCSigma[hsHInd][hsHInd2][hsWInd][hsWInd2][tInd][IInd] = sqrt(XtimesBeta_HCOST(lnhc_varPtr, ageD, 0, PI1, hsHInd, hsWInd, hsHInd2, hsWInd2, 1));
					} //hswind2
				} //hshind2
			} //hwhind
		} //hshind
		for (hsInd = 0; hsInd < HSDIM; hsInd++)  // Current  health so that hsind is lagged
		{
			for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)  // Current  health so that hsind is lagged
			{
				hcSIntercept[sexInd][hsInd][hsInd2][tInd][IInd] =
					XtimesBeta_HCOST(lnhc_meanPtr, ageD, sexInd, PI1, hsInd, hsInd, hsInd2, hsInd2, 0);
				hcSSigma[sexInd][hsInd][hsInd2][tInd][IInd] =
					sqrt(XtimesBeta_HCOST(lnhc_varPtr, ageD, sexInd, PI1, hsInd, hsInd, hsInd2, hsInd2, 0));
			} //hsind2
		}  //hsind

	} //Close on PI

	  //Singles potentially outliving
	  //*?#?* Dimension is reverted here -major bounds overrun issue (noticed on MS compiler) 10/17 RM
	  // Kill off single men & Fill in the remaining women
	  //This never gets executed if couples and single women have the same time horizon.
	for (tInd = TDIMC; tInd < TDIMS; tInd++) //Loop through the couple values and then fill the addiional single men
	{

		printf("This should only execute when single women outlive men. Excess lifespan count: %5d \n", tInd - TDIMC + 1);
		fflush(stdout);

		// Dealing with women throughout
		sexInd = 1;

		ageD = (double)(tInd * MODELPERIOD + TSTART);
		for (IInd = 0; IInd < IDIM; IInd++)
		{
			PI1 = IncomeA[IInd];

			for (hsInd = 0; hsInd < HSDIM; hsInd++)  // LTC, bad health, then good
			{

				survivalProbSM[sexInd][tInd][hsInd][IInd] =
					GetTransProbs(hsCoeffs, ageD, sexInd, PI1, hsInd, HSProbs, 0);
				for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)  // Future health
					hsProbSM[sexInd][tInd][IInd][hsInd][hsInd2] = HSProbs[hsInd2];

				for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)
				{ // Future health
					hcSIntercept[sexInd][hsInd][hsInd2][tInd][IInd] =
						XtimesBeta_HCOST(lnhc_meanPtr, ageD, sexInd, PI1, 0, 0, hsInd2, hsInd2, 0);
					hcSSigma[sexInd][hsInd][hsInd2][tInd][IInd] =
						sqrt(XtimesBeta_HCOST(lnhc_varPtr, ageD, sexInd, PI1, 0, 0, hsInd2, hsInd2, 0));
				}
				// Fill all future values of the single man survival (0s in final period take care of this, but easier to fill whole matrix)     
				survivalProbSM[0][tInd][hsInd][IInd] = 0.0000;
				hsProbSM[0][tInd][IInd][hsInd][0] = 0.0000;
				hsProbSM[0][tInd][IInd][hsInd][1] = 0.0000;
				hsProbSM[0][tInd][IInd][hsInd][2] = 0.0000;

				if (tInd > TDIMC) //keep the end period health cost for single man generated above (as we will pull this of costs of a final member death)
				{
					for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)
					{ // Future health
						hcSIntercept[0][hsInd][hsInd2][tInd][IInd] = -1e8;
						hcSSigma[0][hsInd][hsInd2][tInd][IInd] = 0.0000;
					}
				} //if on tind
			}
		}


	} // loop on final periods for single women
	  //After the final age period health costs (which will always be used combined with death costs). Note 0 indexing means this is TDIMC+1 periods
	  //*?#?*  10/17 RM
	  //Dealth with single men final period in the sfinal period of couples
	tInd = TDIMS;
	// Dealing with women throughout
	sexInd = 1;

	ageD = (double)(tInd * MODELPERIOD + TSTART);
	for (IInd = 0; IInd < IDIM; IInd++)
	{
		PI1 = IncomeA[IInd];

		for (hsInd = 0; hsInd < HSDIM; hsInd++)  // LTC, bad health, then good
		{


			for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)  // Future health

				for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)
				{ // Future health
					hcSIntercept[sexInd][hsInd][hsInd2][tInd][IInd] =
						XtimesBeta_HCOST(lnhc_meanPtr, ageD, sexInd, PI1, 0, 0, hsInd2, hsInd2, 0);
					hcSSigma[sexInd][hsInd][hsInd2][tInd][IInd] =
						sqrt(XtimesBeta_HCOST(lnhc_varPtr, ageD, sexInd, PI1, 0, 0, hsInd2, hsInd2, 0));
				}
			// Fill all future values of the single man survival (0s in final period take care of this, but easier to fill whole matrix)     

			if (tInd > TDIMC) //keep the end period health cost for single man generated above (as we will pull this of costs of a final member death)
			{
				for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)
				{ // Future health
					hcSIntercept[0][hsInd][hsInd2][tInd][IInd] = -1e8;
					hcSSigma[0][hsInd][hsInd2][tInd][IInd] = 0.0000;
				}
			} //if on tind
		}
	}
	//Fill in the final survival probabilities. we don't do this for health costs as they exist in the future

	for (hsInd = 0; hsInd < HSDIM; hsInd++)
	{
		for (IInd = 0; IInd < IDIM; IInd++)
		{
			//NOte that we onlly kill off the TDIMC-1 man and the TDIMS-1 single woman for sure
			survivalProbSM[0][TDIMC - 1][hsInd][IInd] = 0.0000;
			survivalProbSM[1][TDIMS - 1][hsInd][IInd] = 0.0000;
			survivalProbCM[0][TDIMC - 1][hsInd][IInd] = 0.0000;
			//*?#?* Corrected indexing
			//i.e we omit
			//i.e we omit
			// survivalProbCM[1][TDIMC-1][hsind][IInd]=0.0000;
		}
	}


	// *?#?* deathcosts added and lagged health updated RM 09/17
	//man:
	laghealthIntercept[0][GOODHEALTH] = 0.0;
	laghealthIntercept[0][0] = lnhc_meanPtr[16]; //nursing home not including the now active single woman shifter on the lag because accounted for in the health costs
	laghealthIntercept[0][1] = lnhc_meanPtr[14]; //bad health

												 //man:
	laghealthIntercept[1][GOODHEALTH] = 0.0;
	laghealthIntercept[1][0] = lnhc_meanPtr[17]; //nursing home not including the now active single woman shifter on the lag because accounted for in the health costs
	laghealthIntercept[1][1] = lnhc_meanPtr[15]; //bad health

												 //man:
	laghealthVar[0][GOODHEALTH] = 0.0;
	laghealthVar[0][0] = lnhc_varPtr[16]; //nursing home
	laghealthVar[0][1] = lnhc_varPtr[14]; //bad health

										  //man:
	laghealthVar[1][GOODHEALTH] = 0.0;
	laghealthVar[1][0] = lnhc_varPtr[17]; //nursing home
	laghealthVar[1][1] = lnhc_varPtr[15]; //bad health


	for (IInd = 0; IInd < IDIM; IInd++)
	{

		deathcostsIntercept[0][IInd] = lnhc_meanPtr[22] + IncomeA[IInd] * lnhc_meanPtr[24];
		deathcostsIntercept[1][IInd] = lnhc_meanPtr[23] + IncomeA[IInd] * lnhc_meanPtr[25];
		deathcostsVar[0][IInd] = lnhc_varPtr[22] + IncomeA[IInd] * lnhc_varPtr[24];
		deathcostsVar[1][IInd] = lnhc_varPtr[23] + IncomeA[IInd] * lnhc_varPtr[25];
	}

	// Fill in placeholder values for period T+1 
	//*?#?* removed the placeholder values for healthcosts (as backwards looking and now in final member death costs) 08/17 RM
	for (IInd = 0; IInd < IDIM; IInd++)
	{
		for (sexInd = 0; sexInd < 2; sexInd++)   // Income  
		{
			ySM[sexInd][IInd][TDIMS] = 1;

		}
		yCM[IInd][TDIMC] = 1;

	}

	//Switches
	if (switchTax == 0) // added 09/21/04 
	{ //*?#?* Updated, under new continuous tax functions if s the size of average sacrifice parameter
	  // is set to 0, the G&S tax function implies 0 ATR and 0 MTR
		tax_s0 = 0.00000000;
		tax_s1 = 0.00000000;
		//old: 
		//memset(taxMarS,0, taxDim*sizeof(double));  // no tax
		//memset(taxMarC,0, taxDim*sizeof(double));  // no tax
	}

	if (switchY == 0)
	{ //   Annual Income 
		for (tInd = 0; tInd < TDIMC; tInd++)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (sexInd = 0; sexInd < 2; sexInd++) // Single male, single female  
				{

					ySM[sexInd][IInd][tInd] = 0.0;
				}

				yCM[IInd][tInd] = 0.0;
			}
		}

		for (tInd = TDIMC; tInd < TDIMS; tInd++)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (sexInd = 0; sexInd < 2; sexInd++) // Single male, single female  
				{

					ySM[sexInd][IInd][tInd] = 0.0;
				}
			}
		}
	}
	if (switchHCost == 0)
	{
		// Health expense parameters 
		// Survival Probabilities 

		for (tInd = 0; tInd < TDIMS; tInd++)
		{
			for (sexInd = 0; sexInd < 2; sexInd++)
			{
				for (hsInd = 0; hsInd < HSDIM; hsInd++)  // LTC, Bad health, then good
				{
					for (IInd = 0; IInd < IDIM; IInd++)
					{
						for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)  // Current  health so that hsind is lagged
						{
							// *?#?* Replace hcSLogMean with hcSIntercept RM 01/2017          
							// *?#?* Replace  with large negative number (as exponenting) RM 10/2017
							hcSIntercept[sexInd][hsInd][hsInd2][tInd][IInd] = -10000000.0;
							// Old version:
							//  hcSLogMean[sexInd][hsInd][tInd][IInd] = 0.0;
							hcSSigma[sexInd][hsInd][hsInd2][tInd][IInd] = 0.0;
						}
					}
				}
			}
		}

		for (tInd = 0; tInd < TDIMC; tInd++)
		{
			for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
			{
				for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
				{
					for (IInd = 0; IInd < IDIM; IInd++)
					{
						for (hsHInd2 = 0; hsHInd2 < HSDIM; hsHInd2++)  // Current  health so that hsind is lagged
						{  //Malestatus is used only for singles as we evaluaate at the couple level
							for (hsWInd2 = 0; hsWInd2 < HSDIM; hsWInd2++)  // Current  health so that hsind is lagged
							{ // *?#?* Replace  with large negative number (as exponenting) RM 10/2017
								hcCIntercept[hsHInd][hsHInd2][hsWInd][hsWInd2][tInd][IInd] = -10000000.0;
								hcCSigma[hsHInd][hsHInd2][hsWInd][hsWInd2][tInd][IInd] = 0.0000;
							}
						}
					}
				}
			}
		}
		// *?#?* deathcosts added and lagged health updated RM 02/18
		//man:
		laghealthIntercept[0][GOODHEALTH] = 0.0;
		laghealthIntercept[0][0] = 0.0; //nursing home
		laghealthIntercept[0][1] = 0.0; //bad health

										//man:
		laghealthIntercept[1][GOODHEALTH] = 0.0;
		laghealthIntercept[1][0] = 0.0; //nursing home
		laghealthIntercept[1][1] = 0.0; //bad health

										//man:
		laghealthVar[0][GOODHEALTH] = 0.0;
		laghealthVar[0][0] = 0.0; //nursing home
		laghealthVar[0][1] = 0.0; //bad health

								  //man:
		laghealthVar[1][GOODHEALTH] = 0.0;
		laghealthVar[1][0] = 0.0; //nursing home
		laghealthVar[1][1] = 0.0; //bad health


		for (IInd = 0; IInd < IDIM; IInd++)
		{

			deathcostsIntercept[0][IInd] = 0.0;
			deathcostsIntercept[1][IInd] = 0.0;
			deathcostsVar[0][IInd] = 0.0;
			deathcostsVar[1][IInd] = 0.0;
		}
	}


	if (switchMor == 0)
	{
		// Survival Probabilities 

		for (tInd = 0; tInd < TDIMC - 1; tInd++) // JJJJJJ 
		{
			for (sexInd = 0; sexInd < 2; sexInd++)
			{
				for (hsInd = 0; hsInd < HSDIM; hsInd++)  // LTC, Bad health, then good 
				{
					for (IInd = 0; IInd < IDIM; IInd++)
					{
						survivalProbSM[sexInd][tInd][hsInd][IInd] = 1.0;
						survivalProbCM[sexInd][tInd][hsInd][IInd] = 1.0;

					}
				}
			}
		}
		//Account for the extra period of single womanhood in couple
		for (hsInd = 0; hsInd < HSDIM; hsInd++)  // LTC, Bad health, then good 
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				survivalProbCM[1][TDIMC - 1][hsInd][IInd] = 1.0;
			}
		}


		for (tInd = 0; tInd < TDIMS - 1; tInd++) // JJJJJJ 
		{
			for (hsInd = 0; hsInd < HSDIM; hsInd++)  // LTC, Bad health, then good 
			{
				for (IInd = 0; IInd < IDIM; IInd++)
				{
					survivalProbSM[1][tInd][hsInd][IInd] = 1.0;
				}
			}
		}
	}

	// Added by RM 10/21/222 -reconstruct the profiles using the other GAUSS profiles. This reproduces the above code. Alternative is to change the loading
	if (switchRisk == 0)
	{
		for (tInd = 0; tInd < TDIMC; tInd++)
		{

			ageD = (double)(tInd * MODELPERIOD + TSTART);
			for (sexInd = 0; sexInd < 2; sexInd++)
			{

				for (IInd = 0; IInd < IDIM; IInd++)
				{
					PI1 = IncomeA[IInd];



					for (hsInd = 0; hsInd < HSDIM; hsInd++)  //  LTC, bad, then good, 
					{
						//Singles first

						/* XtimesBeta_HCOST(double *coeffs, double age, int sexInd, double PInc,int laghealthStatH,
						int laghealthStatW, int healthStatH, int healthStatW, int couplestatus)
						Below I duplicate hsind and hsind2 to pass the same arguments for men and women, only one of these will be used
						as the couple status is always set to 0*/

						for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)  // Current  health so that hsind is lagged
						{
							hcSIntercept[sexInd][hsInd][hsInd2][tInd][IInd] =
								XtimesBeta_HCOST(lnhc_mean_noriskPtr, ageD, sexInd, PI1, hsInd, hsInd, hsInd2, hsInd2, 0);
							hcSSigma[sexInd][hsInd][hsInd2][tInd][IInd] =
								sqrt(XtimesBeta_HCOST(lnhc_var_noriskPtr, ageD, sexInd, PI1, hsInd, hsInd, hsInd2, hsInd2, 0));
						}


					}




				}

			} //Close on sex

			  // Fill in couples Intercepts and variances for health costs

			  //Select coefficients in the same way as singles

			for (IInd = 0; IInd < IDIM; IInd++)
			{
				PI1 = IncomeA[IInd];

				for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)  /* Husband's health*/
				{
					for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)  /* Wife's health */
					{


						for (hsHInd2 = 0; hsHInd2 < HSDIM; hsHInd2++)  // Current  health so that hsind is lagged
						{  //Malestatus is used only for singles as we evaluaate at the couple level
							for (hsWInd2 = 0; hsWInd2 < HSDIM; hsWInd2++)  // Current  health so that hsind is lagged
							{
								hcCIntercept[hsHInd][hsHInd2][hsWInd][hsWInd2][tInd][IInd] = XtimesBeta_HCOST(lnhc_mean_noriskPtr, ageD, 0, PI1, hsHInd, hsWInd, hsHInd2, hsWInd2, 1);
								hcCSigma[hsHInd][hsHInd2][hsWInd][hsWInd2][tInd][IInd] = sqrt(XtimesBeta_HCOST(lnhc_var_noriskPtr, ageD, 0, PI1, hsHInd, hsWInd, hsHInd2, hsWInd2, 1));
							}
						}
					}
				}
			} //Close on PI


		} // Close on age
		  //After the final age period health costs (which will always be used combined with death costs). Note 0 indexing means this is TDIMC+1 periods
		  //*?#?*  10/17 RM

		tInd = TDIMC;
		ageD = (double)(tInd * MODELPERIOD + TSTART);
		sexInd = 0;
		//COuple values & single men
		for (IInd = 0; IInd < IDIM; IInd++)
		{
			PI1 = IncomeA[IInd];

			for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)  /* Husband's health*/
			{
				for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)  /* Wife's health */
				{


					for (hsHInd2 = 0; hsHInd2 < HSDIM; hsHInd2++)  // Current  health so that hsind is lagged
					{  //Malestatus is used only for singles as we evaluaate at the couple level
						for (hsWInd2 = 0; hsWInd2 < HSDIM; hsWInd2++)  // Current  health so that hsind is lagged
						{
							hcCIntercept[hsHInd][hsHInd2][hsWInd][hsWInd2][tInd][IInd] = XtimesBeta_HCOST(lnhc_mean_noriskPtr, ageD, 0, PI1, hsHInd, hsWInd, hsHInd2, hsWInd2, 1);
							hcCSigma[hsHInd][hsHInd2][hsWInd][hsWInd2][tInd][IInd] = sqrt(XtimesBeta_HCOST(lnhc_var_noriskPtr, ageD, 0, PI1, hsHInd, hsWInd, hsHInd2, hsWInd2, 1));
						} //hswind2
					} //hshind2
				} //hwhind
			} //hshind
			for (hsInd = 0; hsInd < HSDIM; hsInd++)  // Current  health so that hsind is lagged
			{
				for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)  // Current  health so that hsind is lagged
				{
					hcSIntercept[sexInd][hsInd][hsInd2][tInd][IInd] =
						XtimesBeta_HCOST(lnhc_mean_noriskPtr, ageD, sexInd, PI1, hsInd, hsInd, hsInd2, hsInd2, 0);
					hcSSigma[sexInd][hsInd][hsInd2][tInd][IInd] =
						sqrt(XtimesBeta_HCOST(lnhc_var_noriskPtr, ageD, sexInd, PI1, hsInd, hsInd, hsInd2, hsInd2, 0));
				} //hsind2
			}  //hsind

		} //Close on PI

		  //Singles potentially outliving
		  //*?#?* Dimension is reverted here -major bounds overrun issue (noticed on MS compiler) 10/17 RM
		  // Kill off single men & Fill in the remaining women
		  //This never gets executed if couples and single women have the same time horizon.
		for (tInd = TDIMC; tInd < TDIMS; tInd++) //Loop through the couple values and then fill the addiional single men
		{

			printf("This should only execute when single women outlive men. Excess lifespan count: %5d \n", tInd - TDIMC + 1);
			fflush(stdout);

			// Dealing with women throughout
			sexInd = 1;

			ageD = (double)(tInd * MODELPERIOD + TSTART);
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				PI1 = IncomeA[IInd];

				for (hsInd = 0; hsInd < HSDIM; hsInd++)  // LTC, bad health, then good
				{


					for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)
					{ // Future health
						hcSIntercept[sexInd][hsInd][hsInd2][tInd][IInd] =
							XtimesBeta_HCOST(lnhc_mean_noriskPtr, ageD, sexInd, PI1, 0, 0, hsInd2, hsInd2, 0);
						hcSSigma[sexInd][hsInd][hsInd2][tInd][IInd] =
							sqrt(XtimesBeta_HCOST(lnhc_var_noriskPtr, ageD, sexInd, PI1, 0, 0, hsInd2, hsInd2, 0));
					}

					if (tInd > TDIMC) //keep the end period health cost for single man generated above (as we will pull this of costs of a final member death)
					{
						for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)
						{ // Future health
							hcSIntercept[0][hsInd][hsInd2][tInd][IInd] = -1e8;
							hcSSigma[0][hsInd][hsInd2][tInd][IInd] = 0.0000;
						}
					} //if on tind
				}
			}


		} // loop on final periods for single women
		  //After the final age period health costs (which will always be used combined with death costs). Note 0 indexing means this is TDIMC+1 periods
		  //*?#?*  10/17 RM
		  //Dealth with single men final period in the sfinal period of couples
		tInd = TDIMS;
		// Dealing with women throughout
		sexInd = 1;

		ageD = (double)(tInd * MODELPERIOD + TSTART);
		for (IInd = 0; IInd < IDIM; IInd++)
		{
			PI1 = IncomeA[IInd];

			for (hsInd = 0; hsInd < HSDIM; hsInd++)  // LTC, bad health, then good
			{


				for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)  // Future health

					for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)
					{ // Future health
						hcSIntercept[sexInd][hsInd][hsInd2][tInd][IInd] =
							XtimesBeta_HCOST(lnhc_mean_noriskPtr, ageD, sexInd, PI1, 0, 0, hsInd2, hsInd2, 0);
						hcSSigma[sexInd][hsInd][hsInd2][tInd][IInd] =
							sqrt(XtimesBeta_HCOST(lnhc_var_noriskPtr, ageD, sexInd, PI1, 0, 0, hsInd2, hsInd2, 0));
					}
				// Fill all future values of the single man survival (0s in final period take care of this, but easier to fill whole matrix)     

				if (tInd > TDIMC) //keep the end period health cost for single man generated above (as we will pull this of costs of a final member death)
				{
					for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)
					{ // Future health
						hcSIntercept[0][hsInd][hsInd2][tInd][IInd] = -1e8;
						hcSSigma[0][hsInd][hsInd2][tInd][IInd] = 0.0000;
					}
				} //if on tind
			}
		}


		// *?#?* deathcosts added and lagged health updated RM 09/17
		//man:
		laghealthIntercept[0][GOODHEALTH] = 0.0;
		laghealthIntercept[0][0] = lnhc_mean_noriskPtr[16]; //nursing home not including the now active single woman shifter on the lag because accounted for in the health costs
		laghealthIntercept[0][1] = lnhc_mean_noriskPtr[14]; //bad health

													 //man:
		laghealthIntercept[1][GOODHEALTH] = 0.0;
		laghealthIntercept[1][0] = lnhc_mean_noriskPtr[17]; //nursing home not including the now active single woman shifter on the lag because accounted for in the health costs
		laghealthIntercept[1][1] = lnhc_mean_noriskPtr[15]; //bad health

													 //man:
		laghealthVar[0][GOODHEALTH] = 0.0;
		laghealthVar[0][0] = lnhc_var_noriskPtr[16]; //nursing home
		laghealthVar[0][1] = lnhc_var_noriskPtr[14]; //bad health

											  //man:
		laghealthVar[1][GOODHEALTH] = 0.0;
		laghealthVar[1][0] = lnhc_var_noriskPtr[17]; //nursing home
		laghealthVar[1][1] = lnhc_var_noriskPtr[15]; //bad health


		for (IInd = 0; IInd < IDIM; IInd++)
		{

			deathcostsIntercept[0][IInd] = lnhc_mean_noriskPtr[22] + IncomeA[IInd] * lnhc_mean_noriskPtr[24];
			deathcostsIntercept[1][IInd] = lnhc_mean_noriskPtr[23] + IncomeA[IInd] * lnhc_mean_noriskPtr[25];
			deathcostsVar[0][IInd] = lnhc_var_noriskPtr[22] + IncomeA[IInd] * lnhc_var_noriskPtr[24];
			deathcostsVar[1][IInd] = lnhc_var_noriskPtr[23] + IncomeA[IInd] * lnhc_var_noriskPtr[25];
		}




	}
	

	// Added by RM 10/21/222
	if (switchContrisk == 0)
	{

		//First eliminate the variance associated with death
		for (IInd = 0; IInd < IDIM; IInd++)
		{

			deathcostsVar[0][IInd] = 0.0;
			deathcostsVar[1][IInd] = 0.0;
		}
		//Second eliminate variances arrising from lagged health at death (should be simulation)
											//man:
		laghealthVar[0][GOODHEALTH] = 0.0;
		laghealthVar[0][0] = 0.0; //nursing home
		laghealthVar[0][1] = 0.0; //bad health

								  //man:
		laghealthVar[1][GOODHEALTH] = 0.0;
		laghealthVar[1][0] = 0.0; //nursing home
		laghealthVar[1][1] = 0.0; //bad health

		//Third eliminate the remaining variances and simultaneously load the risk free profile for the singles mean

		for (tInd = 0; tInd < TDIMS; tInd++)
		{
			ageD = (double)(tInd * MODELPERIOD + TSTART);


			for (sexInd = 0; sexInd < 2; sexInd++)
			{
				for (hsInd = 0; hsInd < HSDIM; hsInd++)  // LTC, Bad health, then good
				{
					for (IInd = 0; IInd < IDIM; IInd++)
					{
						PI1 = IncomeA[IInd];

						for (hsInd2 = 0; hsInd2 < HSDIM; hsInd2++)  // Current  health so that hsind is lagged
						{
							// *?#?* Calculate with the riskless profile     RM 10/21/22
							hcSIntercept[sexInd][hsInd][hsInd2][tInd][IInd] = XtimesBeta_HCOST(lnhc_mean_noriskPtr, ageD, sexInd, PI1, hsInd, hsInd, hsInd2, hsInd2, 0);

							hcSSigma[sexInd][hsInd][hsInd2][tInd][IInd] = 0.0;
						}
					}
				}
			}
		}

	}
	free(hsCoeffs);
	return 1;
}


void GetFinalMemberDeathCosts(double deathcostsFinalMemberC[TDIMC + 1][IDIM][HSDIM][HSDIM][ZETADIM][XIDIM], double deathcostsFinalMemberS[2][TDIMS + 1][IDIM][HSDIM][ZETADIM][XIDIM], int hardcode)
//Awkwardness as with bequests about timing here- this iomposes the correct timing, but dates it as if contemporaneous rather than end of period/start of new period
//*?#?*Added by RM 08/17
//HARDCODE IS THE GOOD HEALTH STATUS for tomorrow (THE EXCLUDED CATEGORY). When someone dies none of the other dummies are activated
/*  Adapted by RM 08/17 to updated zetaindN to zetaInd in the calculations below*/

{
	int tInd, IInd, zetaInd, xiInd, hsInd, hsHInd, hsWInd;

	for (tInd = 0; tInd < TDIMC; tInd++) //Note the medical expenses must go all of the way now
	{



		for (IInd = 0; IInd < IDIM; IInd++)
		{

			for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
			{



				for (xiInd = 0; xiInd < XIDIM; xiInd++)
				{ //Singles first

					for (hsInd = 0; hsInd < HSDIM; hsInd++)
					{
						// *?#?* Updated RM 09/17 to allow for dependence on lagged health        	
						//single man dying
						deathcostsFinalMemberS[0][tInd][IInd][hsInd][zetaInd][xiInd] = hcSIntercept[0][hsInd][hardcode][tInd + 1][IInd] + deathcostsIntercept[0][IInd] + (sqrt(pow(hcSSigma[0][hsInd][hardcode][tInd + 1][IInd], 2.0) + deathcostsVar[0][IInd])) * (zetaA[zetaInd] + xiA[xiInd]);
						//single woman  dying
						deathcostsFinalMemberS[1][tInd][IInd][hsInd][zetaInd][xiInd] = hcSIntercept[1][hsInd][hardcode][tInd + 1][IInd] + deathcostsIntercept[1][IInd] + (sqrt(pow(hcSSigma[1][hsInd][hardcode][tInd + 1][IInd], 2.0) + deathcostsVar[1][IInd])) * (zetaA[zetaInd] + xiA[xiInd]);
					} //looping over health stat
					for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
					{
						for (hsWInd = 0; hsWInd < HSDIM; ++hsWInd)
						{

							// *?#?* Updated RM 09/17 to allow for dependence on lagged health - it also adjust for the variance coefficients
							deathcostsFinalMemberC[tInd][IInd][hsHInd][hsWInd][zetaInd][xiInd] = hcCIntercept[hsHInd][hsWInd][hardcode][hardcode][tInd + 1][IInd] + deathcostsIntercept[0][IInd] + deathcostsIntercept[1][IInd] + (sqrt(pow(hcCSigma[hsHInd][hsWInd][hardcode][hardcode][tInd + 1][IInd], 2.0) + deathcostsVar[0][IInd] + deathcostsVar[1][IInd])) * (zetaA[zetaInd] + xiA[xiInd]);
						} //husband health stat
					} //wife health stat



				} //xi


			} //zeta

		}//PI




	}//T


	 // Fill in couples Intercepts and variances for health costs


	 // Kill off single men & Fill in the remaining women
	for (tInd = TDIMC; tInd < TDIMS; tInd++) //Loop through the couple values and then fill the addiional single men
	{


		// Dealing with women throughout
		for (IInd = 0; IInd < IDIM; IInd++)
		{

			for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
			{



				for (xiInd; xiInd < XIDIM; xiInd++)
				{ //Singles first
					for (hsInd = 0; hsInd < HSDIM; hsInd++)
					{
						//single man dying, 0s because at the extra period
						deathcostsFinalMemberS[0][tInd][IInd][hsInd][zetaInd][xiInd] = 0.0;
						//single woman  dying
						deathcostsFinalMemberS[1][tInd][IInd][hsInd][zetaInd][xiInd] = hcSSigma[1][hsInd][hardcode][tInd + 1][IInd] + deathcostsIntercept[1][IInd] + hcSSigma[1][hsInd][hardcode][tInd + 1][IInd] * (zetaA[zetaInd] + xiA[xiInd]);
						//Both couple members die is already filled
					}


				} //xi


			} //zeta

		}//PI




	} // loop on final periods for single women
}
/*  Adapted by RM 15/05/17 to allow for couples and PI, based on JBJ:  01/30/12  (AER paper)  */

double GetTransProbs(double** hsCoeffs, double age, int sexInd,
	double PInc, int healthStat, double HSProbs[HSDIM], int couplestatus)
{
	double totProduct, MVLsum, survprob;
	int iHS;

	MVLsum = 1; // Death is the benchmark state

	for (iHS = 0; iHS < HSDIM; iHS++) // iHS indexes future health, healthStat indexes current health
	{
		totProduct = XtimesBeta(hsCoeffs[iHS], age, sexInd, PInc, healthStat, couplestatus);
		HSProbs[iHS] = exp(totProduct);
		MVLsum += exp(totProduct);
	}

	survprob = 1 - 1 / MVLsum;

	for (iHS = 0; iHS < HSDIM; iHS++)
	{
		HSProbs[iHS] = HSProbs[iHS] / MVLsum;
		HSProbs[iHS] = HSProbs[iHS] / survprob; // Probability conditional on surviving
	}

	return(survprob);
}

/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/*  Evaluate inner product for MV logit or preference shocks                      */
/* *?#?* Adapted by RM 15/05/17 to allow for couples and PI, based on JBJ:  01/30/12 (AER paper)   */
// *?#?* Updated by by RM 06/2017 to correct I/O with GAUSS
double XtimesBeta(double* coeffs, double age, int sexInd, double PInc, int healthStat, int couplestatus)
{
	double totProduct;
	int iHS, i;

	totProduct = coeffs[0] + coeffs[1] * age + coeffs[2] * pow(age, 2) / 100 +
		coeffs[3] * pow(age, 3) / 10000 + (coeffs[4] + coeffs[6] * age) * PInc +
		coeffs[5] * pow(PInc, 2);

	if (couplestatus == 1)
		totProduct += (coeffs[10] + coeffs[11] * age + coeffs[13] * PInc); // Couples

	if (sexInd == 0)
		totProduct += (coeffs[7] + coeffs[8] * age + coeffs[9] * PInc + (double)(couplestatus * coeffs[12]));  // Male, including the couple interaction

																											 //hs=0, NH, hs=1, BH, hs=2 GH. Coeffs 14 & 15 BH, 16 & 17 GH. SO we count up    
	for (iHS = 1; iHS < HSDIM; iHS++) // Health Dummies, skip GH i.e. <2
	{
		if (healthStat == iHS) //Adjusted coefficient vector
		{
			i = 14 + (iHS - 1) * 2; //ihs=1 count 14 so 14 & 15 when in BH
			totProduct += (coeffs[i] + coeffs[i + 1] * age);
		}
	}

	return(totProduct);
}

/*  Evaluate inner product for MV logit or preference shocks                      */
/*  *?#?* Adapted by RM 15/05/17 to allow for 2 health statuses, based on JBJ:  01/30/12   */
//If couplestatus is 0 only the laghealthStatW (H) and healthstatW (H) are used for the correct gender
// *?#?* Updated by by RM 06/2017 to correct I/O with GAUSS
// *?#?* Updated by by RM 09/2017 to correct I/O with GAUSS for laffed health status and death cost
// *?#?* Updated by by RM 08/2019 to correct I/O with GAUSS for lagged health status and death cost and single interactions

double XtimesBeta_HCOST(double* coeffs, double age, int sexInd, double PInc, int laghealthStatH, int laghealthStatW, int healthStatH, int healthStatW, int couplestatus)
{
	//See documentation for clarification on order.
	double totProduct;
	int iHS, i;

	totProduct = coeffs[0] + coeffs[1] * age + coeffs[2] * pow(age, 2) / 100 +
		coeffs[3] * pow(age, 3) / 10000 + coeffs[4] * pow(age, 4) / 1000000 + (coeffs[5] + coeffs[7] * age) * PInc +
		coeffs[6] * pow(PInc, 2);

	//Single household:
	if (couplestatus == 0)
	{
		if (sexInd == 0)
		{
			totProduct += (coeffs[8] + coeffs[18] * age + coeffs[20] * pow(age, 2) / 100);  // Male, -no couple interaction as evaluated at the household level
			for (iHS = 0; iHS < HSDIM - 1; iHS++) // Health Dummies, healthstat3 is the excluded group
			{
				if (healthStatH == iHS) //Adjusted coefficient vector
				{
					i = 12 - (iHS) * 2; //Nursing Home is the 0 index on healthstat ihs=1 count from 10 so so count back. ihs=1 count from 12 so as to skip the women's coefficient
					totProduct += coeffs[i];
				}
				if (laghealthStatH == iHS) //Adjusted coefficient vector
				{
					i = 16 - (iHS) * 2;  //Nursing Home is the 0 index on healthstat so count back. ihs=1 count from 16 so as to skip the women's coefficient
					totProduct += coeffs[i];
				}

			}
			//hardcode these checks for the single nusing interaction
			if (healthStatH == 0) //Nursing home single man dummy
			{
				i = 26; //27-1 
				totProduct += coeffs[i];
			}
			if (laghealthStatH == 0) //Lag Nursing home single man dummy
			{
				i = 28; //29-1 
				totProduct += coeffs[i];
			}

		}
		else if (sexInd == 1)
		{
			totProduct += (coeffs[9] + coeffs[19] * age + coeffs[21] * pow(age, 2) / 100);
			for (iHS = 0; iHS < HSDIM - 1; iHS++) // Health Dummies, healthstat3 is the excluded group
			{
				if (healthStatW == iHS) //Adjusted coefficient vector
				{
					i = 13 - (iHS) * 2; //Nursing Home is the 0 index on healthstat ihs=1 count from 1 so as to skip the women's coefficient
					totProduct += coeffs[i];
				}

				if (laghealthStatW == iHS) //Adjusted coefficient vector
				{
					i = 17 - (iHS) * 2;  //Nursing Home is the 0 index on healthstat so count back. ihs=1 count from 14 so as to skip the women's coefficient
					totProduct += coeffs[i];
				}

			}
			//Hardcode these checks for the single nusing interaction
			if (healthStatW == 0) //Nursing home single woman dummy
			{
				i = 27; //28-1 
				totProduct += coeffs[i];
			}
			if (laghealthStatW == 0) //Lag Nursing home single woman dummy
			{
				i = 29; //30-1 
				totProduct += coeffs[i];
			}


		}
		else
		{
			printf("ERROR need sexInd to construct health costs\n");
			fflush(stdout);

		}
	}
	else if (couplestatus == 1)
	{

		for (iHS = 0; iHS < HSDIM - 1; iHS++) // Health Dummies, healthstat3 is the excluded group
		{
			//Pick up all of the dummies
			if (healthStatH == iHS) //Adjusted coefficient vector
			{
				i = 12 - (iHS) * 2; //Nursing Home is the 0 index on healthstat ihs=1 count from 10 so so count back. ihs=1 count from 12 so as to skip the women's coefficient
				totProduct += coeffs[i];
			}

			if (laghealthStatH == iHS) //Adjusted coefficient vector
			{
				i = 16 - (iHS) * 2;  //Nursing Home is the 0 index on healthstat so count back. ihs=1 count from 16 so as to skip the women's coefficient
				totProduct += coeffs[i];
			}
			if (healthStatW == iHS) //Adjusted coefficient vector
			{
				i = 13 - (iHS) * 2; //Nursing Home is the 0 index on healthstat ihs=1 count from 1 so as to skip the women's coefficient
				totProduct += coeffs[i];
			}

			if (laghealthStatW == iHS) //Adjusted coefficient vector
			{
				i = 17 - (iHS) * 2;  //Nursing Home is the 0 index on healthstat so count back. ihs=1 count from 14 so as to skip the women's coefficient
				totProduct += coeffs[i];
			}

		}
	}
	else
	{
		printf("ERROR need couplestatus to construct health costs\n");
		fflush(stdout);

	}

	return(totProduct);
}


/* old:
Evaluate inner product for MV logit or preference shocks
*?#?* Adapted by RM 15/05/17 to allow for 2 health statuses, based on JBJ:  01/30/12
If couplestatus is 0 the laghealthStatW and healthstatW are unused
*?#?* Updated by by RM 06/2017 to correct I/O with GAUSS

double XtimesBeta_HCOST(double *coeffs, double age, int sexInd, double PInc,int laghealthStatH, int laghealthStatW, int healthStatH, int healthStatW, int couplestatus)
{
//See documentation for clarification on order.
double totProduct;
int iHS, i;

totProduct = coeffs[0] + coeffs[1] * age + coeffs[2] * pow(age, 2) / 100 +
coeffs[3] * pow(age, 3) / 10000 + (coeffs[4] + coeffs[6] * age)*PInc +
coeffs[5] * pow(PInc, 2);


if (sexInd == 0)
totProduct += (coeffs[7] + coeffs[8] * age + coeffs[9] * PInc);  // Male, -no couple interaction as evaluated at the household level

//hs=0, NH, hs=1, BH, hs=2 GH. Coeffs 10 & 11  BH, 12 & 13 GH. SO we count up
for (iHS = 1; iHS<HSDIM; iHS++) // Health Dummies
{
if (healthStatH == iHS) //Adjusted coefficient vector
{
i = 10 + (iHS - 1) * 2; //ihs=1 count from 12 so 12 & 13 when in BH
totProduct += (coeffs[i] + coeffs[i + 1] * age);
}
}

if (couplestatus == 1)
{

totProduct += (coeffs[14] + coeffs[15] * age + coeffs[16] * PInc); // Couples
//Second health status: hs=0, NH, hs=1, BH, hs=2 GH. Coeffs 17 & 18  BH, 19 & 20 NH. SO we count down
for (iHS = 1; iHS<HSDIM; iHS++) // Health Dummies
{
if (healthStatW == iHS) //Adjusted coefficient vector
{
i = 17 + (iHS - 1) * 2; // ihs=1 count from 17 so 17 & 18 when in BH
totProduct += (coeffs[i] + coeffs[i + 1] * age);
}
}
}// On couple status

return(totProduct);
}

*/

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//  LOGIT  

double Logit(double x)
{
	return exp(x) / (1 + exp(x));
}
// *?#?* added to deal with health statuses next period (care home) 01/2017
// When using this is the rest of the code, maintain the assumption that the first
//outcome is good health (which would have a numerator of 1) which was used when there
//were only two health statuses. To calculate the two probabilities we need, we will call
//this twice flipping x and y
double Multi3Logit(double x, double y)
{
	return exp(x) / (1 + exp(x) + exp(y));
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//  LOGITSQRT  

double LogitSQRT(double x)
{
	return sqrt(exp(x) / (1 + exp(x)));
}
//  *?#?* Commented out TwoYearToOneYear as no longer needed under 2 year estimation
// RM 01/2017
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/*  TWOYEARTOONEYEAR:  Converts 2-year transition probes to 1-year probs
Using formula by O. Nartova
gg = pr(h_t+2=good|h_t=good); bb = pr(h_t+2=bad|h_t=bad)
_g = pr(h_t+1=good|h_t=good); _b = pr(h_t+1=bad|h_t=bad)
*/
/*
void TwoYearToOneYear(double gg, double bb, double *_g, double *_b)
{
double big_A, big_B, big_C;

big_A = 2-gg-bb;
big_B = 2*(gg-1);
big_C = 1-bb-gg+(bb*bb);

*_b   = -big_B + sqrt(pow(big_B,2) - 4*big_A*big_C);
*_b   = (*_b)/(2*big_A);
*_g   = ( (1-bb) - (*_b)*(1-(*_b)) )/(1-(*_b));

return;
}*/

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//  GLOBDEREF:  Dereference a bunch of pointers to C++ globals  
//==== Modified 2/21/08 by JBJ ====

//  *?#?* Updated where asset vector parameter values are stored (when reading in). 
// This is due to inconsistency between this version of global dereferencing and the
// rest of the program. Now have 2 different consumption floors and no estate taxation
// to deal with. -RM 01/2017
//  *?#?* Updated to make I/o consistent with GAUSS -RM 06/2017 


int globderef(double* prefvecPtr, double* asstvecPtr, double* hcostvecPtr,
	double* simvecPtr, double* agevecPtr, double* switchvecPtr)
{
	/* Flow utility parameters:
	beta = discount factor
	d(m(i)) = 1+d*1{m(i) = good}
	u(c, m(i)) = d(m(i))*(c^(1-nu))/(1-nu)
	*/

	TSTART = (int)floor(rounder + agevecPtr[0]);
	MODELPERIOD = (int)floor(rounder + agevecPtr[2]);
	WIFEAGEDIF = (int)floor(rounder + agevecPtr[3]) / MODELPERIOD;


	delta[GOODHEALTH] = 0.0; //Normalise Good Health to zero.
	delta[0] = prefvecPtr[0]; //Nursing home
	delta[1] = prefvecPtr[1]; //bad health
	beta = pow(prefvecPtr[2], ((double)MODELPERIOD)); //Discount --read in annual value
	nu = prefvecPtr[3]; //CRRA
						//*?#?* Added eta= consumption equivalence scale for couples
						// omega =the weight on surviving spouse *NOTE:this doesn't appear in the paper RM 01/2017 


	omega = prefvecPtr[4]; //weight on surviving spouse

	eta = prefvecPtr[11]; // Consumption equivalence scale
						  //  *?#?*  No estate tax, additional consumption floor. Moved up interest rate parameters
	cMinS = ((double)MODELPERIOD) * asstvecPtr[0]; // Minimun consumption provided by the government to singles read in annual value
	cMinC = ((double)MODELPERIOD) * asstvecPtr[1]; // Minimun consumption provided by the government to couples   read in annual value

												 // interest rate r is an i.i.d. random variable, with mean mu_r and variance (sigma_r)^2. 
	mu_r = asstvecPtr[4];
	sigma_r = asstvecPtr[5];

	// Old version in 2014 code
	//    cMin   = asstvecPtr[0]; // Minimun consumption provided by the government 
	//    tauBeq = asstvecPtr[1]; // Estate tax rate 
	//    exBeq  = asstvecPtr[2]; // Estate tax exemptiohcCInterceptn level 

	// // interest rate r is an i.i.d. random variable, with mean mu_r and variance (sigma_r)^2. 
	//    mu_r          = asstvecPtr[3];
	//    sigma_r       = asstvecPtr[4]; 

	rhoHc = hcostvecPtr[0];
	sigma_zeta = sqrt(hcostvecPtr[1]);
	sigma_epsilon = sqrt(hcostvecPtr[2]);
	sigma_xi = sqrt(hcostvecPtr[3]);
	medex_bottomcode = hcostvecPtr[4]; // JBJ:  7/14/08 

	nsims = (int)floor(rounder + simvecPtr[0]);
	TDimSims = (int)floor(rounder + simvecPtr[1]);



	switchMor = (int)floor(rounder + switchvecPtr[0]);
	switchBeta = (int)floor(rounder + switchvecPtr[1]);
	switchY = (int)floor(rounder + switchvecPtr[2]);
	switchHCost = (int)floor(rounder + switchvecPtr[3]);
	switchTax = (int)floor(rounder + switchvecPtr[4]);
	switchZeta = (int)floor(rounder + switchvecPtr[5]);
	switchXi = (int)floor(rounder + switchvecPtr[6]);
	switchR = (int)floor(rounder + switchvecPtr[7]);
	switchBeq = (int)floor(rounder + switchvecPtr[8]);
	switchGender = (int)floor(rounder + switchvecPtr[9]);
	//*?#?* added switchCouple back in- referred to in the code. We could set it as 1 at the start, but
	// it should be useful for verifying output RM 01/2017
	switchCouple = (int)floor(rounder + switchvecPtr[10]); // 0: only solve single case, 1: single+couple 
	switchHouse = (int)floor(rounder + switchvecPtr[11]); // 0: only solve single case, 1: single+couple  
	switchRisk = (int)floor(rounder + switchvecPtr[12]); // 0: deterministic medex profile for singles+couples, 1: standard  added RM 10/21/22
	switchContrisk = (int)floor(rounder + switchvecPtr[13]); // 0: deterministic medex profile for singles, 1: standard  added RM 10/21/22

	if (switchBeta == 1) beta = 1;

	/* Bequest utility parameters for singles
	Phi_j(b_net) = phi_j*[(b_net+K_j)^(1-nu)]/[1-nu] */


	//*?#?* case ensitivity and adding phi1,2 k1,2 which did not have values assigned previously. Updated
	//indexes due to fix above RM 01/2017 

	phi0 = prefvecPtr[5] * ((double)switchBeq); //bequest weight for singles
	k0 = prefvecPtr[6]; //Bequest luxury for singles -adjust for two years
	phi1 = prefvecPtr[7] * ((double)switchBeq);
	k1 = prefvecPtr[8];
	phi2 = prefvecPtr[9] * ((double)switchBeq);
	k2 = prefvecPtr[10];
	// Old version in 2014 code
	//phi0 = prefvecPtr[3]*((double) switchBeq);
	//K0   = prefvecPtr[4];

	//Fill in disregards and the Social Security Supplemental Income
	//*?#?* Added RM 01/19

	IncDisregardS = ((double)MODELPERIOD) * asstvecPtr[6];
	SSI_IncS = ((double)MODELPERIOD) * asstvecPtr[7];
	AssetDisregardS = ((double)MODELPERIOD) * asstvecPtr[8];
	eta_FPL = asstvecPtr[9];
	IncDisregardC = IncDisregardS * eta_FPL;
	SSI_IncC = SSI_IncS * eta_FPL;
	AssetDisregardC = AssetDisregardS * eta_FPL;


	return 1;
}


/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/*  GETASSIGNMENTVEC:  Allocate points on a state vector across nodes             */
/*                     Uses Sangeeta Pratap's allocation trick                    */

int* getAssignmentVec(int numPoints, int numNodes)
{
	int numBlocks, iBlock, iNode, iPoint, thisPoint;
	double nb2;
	int* assignmentVec;

	assignmentVec = (int*)calloc(numPoints, sizeof(int));

	// for (iPoint=0; iPoint<numPoints; iPoint++)
	//    assignmentVec[iPoint] = iPoint;

	nb2 = ((double)numPoints) / ((double)numNodes);
	numBlocks = (int)ceil(nb2);
	iPoint = 0;

	// Now scramble, by pulling numbers from different "blocks" 
	for (iNode = 0; iNode < numNodes; iNode++)
	{
		for (iBlock = 0; iBlock < numBlocks; iBlock++)
		{
			thisPoint = iBlock * numNodes + iNode + 1;
			if (thisPoint > numPoints) { continue; }   // Recall that indexing starts at zero
			assignmentVec[iPoint] = thisPoint - 1;
			iPoint += 1;
		}
	}

	return assignmentVec;
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/*  SETUPSIM:  Initialize matrices that hold simulation results
Each row of dataMat is a subsection of dataVec
This economizes on memory and reduces copying
*/
double** SetUpSim(double* dataVec, int extrayears)

{
	double** dataMat;
	int iYear;

	dataMat = (double**)malloc((TDimSims + extrayears) * sizeof(double*));
	for (iYear = 0; iYear < (TDimSims + extrayears); iYear++)
	{
		dataMat[iYear] = &dataVec[iYear * nsims];
	}

	return dataMat;
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/*  FREESIM:  Deallocate memory for matrices that hold simulation results
Each row of dataMat is a subsection of dataVec
This economizes on memory and reduces copying -*?#? added RM 11/17
*/
void FreeSim(double* dataVec, int extrayears, double** dataMat)

{
	/*  int iYear;

	/*for (iYear = 0; iYear<(TDimSims + extrayears); iYear++)
	{
	free(dataMat[iYear]);
	}
	*/
	free(dataMat);
	free(dataVec);
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//  ZEROMAT:  Initializes matrix structure and fills it with zeros  

GMatrix zeromat(unsigned int recsize)
{
	GMatrix mat = { 1, 1 };
	mat.m = recsize;
	mat.n = 1;
	mat.data = (double*)calloc(recsize, sizeof(double));
	return mat;
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//  SWITCHEM:  Switches two pointer addresses  

void switchem(double** dataPtr, double** tempPtr)
{
	double* tempPtr2;
	tempPtr2 = *dataPtr;  // dataPtr, tempPtr are pointers to pointers.  
	*dataPtr = *tempPtr;  // Dereferencing them yields memory addresses, 
	*tempPtr = tempPtr2;  // rather than values. 
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
void copyit(double* permvec, double* tempvec, int recsize)
{
	int i;
	for (i = 0; i < recsize; i++) permvec[i] = tempvec[i];
	return;
}
//--------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/* Solve value function for t = 1, ..., T
Singles case
& scrambling of asset grid in parallel RM 08/17
*/
void GetRulesSingle(int iAssetsmin, int iAssetsmax, int* assetAssignments)
{
	int tInd, cashInd, cashInd2, i, IInd, hsInd, zetaInd, consumInd;
	double maximum = 0.0;       // used in maximization to record maximum
	int index = 0;              // used in maximization to record index of maximizer 
	double valueM[CONSUMDIM];  // intermediate value function, used in maximization 
	double* tempvec;
	int recsize = IDIM * HSDIM * ZETADIM * CASHDIM;
	tempvec = (double*)calloc(recsize, sizeof(double));

	if ((useMPI < 2) || (rank == (size - 1)))
		printf("Solving for SINGLES. \n ");
	fflush(stdout);


	// Switched order of loops to make it more intuitive with the parallelization **** 04/2014       
	// COH is now only inside the age loop, over which we cannot parallelize.  
	for (tInd = (TDIMS - 1); tInd >= 0; tInd--) // today's age
	{
		if ((useMPI < 2) || (rank == (size - 1))) printf("Age=%d \n ", tInd * MODELPERIOD + TSTART); // *?#?* Added Model period to print correct ages RM 01/2017
		fflush(stdout);
		if ((useMPI < 2) || (rank == (size - 1))) printf("Precompute Bequest Expectation: Age=%d \n ", tInd * MODELPERIOD + TSTART); // *?#?* Added Model period to print correct ages RM 1/2018
		fflush(stdout);

		//Precompute expected bequests for final member death 01/2018 RM:
		GetUtilityBeqS(bequestUSM, iAssetsmin, iAssetsmax, assetAssignments, tInd);   // Find utility from bequest matrix    *?#?* Replaced BequestUM with BequestUSM 01/2017 //*?#?* scrambling of asset grid in parallel RM 08/17


		for (i = 0; i < 2; i++) // gender
		{
			for (cashInd2 = iAssetsmin; cashInd2 < iAssetsmax; cashInd2++)   // COH
			{ // *?#?* Reversed coh and gender due to MPI implementation RM 03/2017
				cashInd = assetAssignments[cashInd2]; // "Scramble" gridpoints across clusters.  JBJ:  5/30/14 *?#?* added RM 08/2017


				for (IInd = 0; IInd < IDIM; IInd++) // PI
				{
					for (hsInd = 0; hsInd < HSDIM; hsInd++) // today's health
					{
						for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++) // today's persistent medex shock
						{
							// maximization on each node 
							maximum = -1000000.0;  // maximum utility 
							index = 0;           // Index of consumption giving maximum utility 

												 // loop through possible consumption choice 
							for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
							{
								//if (consumS[consumInd] <= cashS[cashInd]) OLD VERSION
								if (consumS[consumInd] < cashS[cashInd] || fabs(consumS[consumInd] - cashS[cashInd]) < ABS_TOL) // *?#?* Added almost exact comparison. Old version above RM 01/2017
								{
									valueM[consumInd] = GetValueSingle(i, tInd, IInd, hsInd, zetaInd, cashInd, consumInd);

									/*                        if ((tInd==28)&(hsInd==0)&(IInd==0))
									{
									fprintf(sumP,"%10.5f", sum);
									fprintf(sumP,"%10.5f %10.5f\n",utilitySM[hsInd][consumInd],valueM[consumInd] );
									}
									*/
									// maximization over all possible consumption choices 
									if (maximum < valueM[consumInd])
									{
										maximum = valueM[consumInd];
										index = consumInd;
									} //maximization 
								}
								else  // consumption choice is bigger than available cash on hand 
								{
									break;
								}
							}// end loop through consumption grid 
							 // record value function for this period and policy function 
							valueFunSM[i][tInd][IInd][hsInd][zetaInd][cashInd] = maximum;
							consumFunSM[i][tInd][IInd][hsInd][zetaInd][cashInd] = consumS[index];
							// *?#?*
							// Used the consumption grid for couples, changed to singles RM 12/12/2016

							bequestFunSM[i][tInd][IInd][hsInd][zetaInd][cashInd] = cashS[cashInd] - consumS[index];

							// 2014 version: 
							//  bequestFunSM[i][tInd][IInd][hsInd][zetaInd][cashInd] = cashS[cashInd] -consumC[index]; 
						}// end loop through persistent health shock        
					}// end loop through health status    
				}// end loop through permanent income    

			} // end loop for cash on hand 
			  // MPI-specific Code:  Merge output from different processors 
			if (useMPI == 2)
			{
				//Begin the automated commenting *?#?*- Added control sequence RM 03/17
#if(MPI_COMMENT==1)
				MPI_Allreduce(valueFunSM[i][tInd][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
				copyit(valueFunSM[i][tInd][0][0][0], tempvec, recsize);
				MPI_Allreduce(bequestFunSM[i][tInd][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
				copyit(bequestFunSM[i][tInd][0][0][0], tempvec, recsize);
				MPI_Allreduce(consumFunSM[i][tInd][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
				copyit(consumFunSM[i][tInd][0][0][0], tempvec, recsize);
#endif     //(MPI_COMMENT==1)
			} //Close if on MPI use
#if(MPI_COMMENT==2) //conditional compile on using openMP *?#?*- Added control sequence RM 11/17
#pragma omp barrier //wait until every processor has hit this point
#endif  //close on Openmp ---NOTE TO SELF: IN THIS CASE CAN IT GO OUTSIDE THE GENDER LOOP? CAN I DO THE SAME WITH MPI
		}  // end loop through gender 

	} // end loop through age 
	free(tempvec);
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/*
For each given value of state variables today.
Calculate the expected value of the value function at each choice of consumption.
Singles case
*/
double GetValueSingle(int i, int tInd, int  IInd, int hsInd, int zetaInd,
	int cashInd, int consumInd)
{
	int  rInd, hsIndN, zetaIndN, xiInd;
	double cashnet, savings, medcostshifter, cashOnHand;
	double DisA, DisI;	//Intermediate- the household's disregardable income added 01/18 RM *?#?*
	double sum; // sum is the expected value next period    
	sum = 0.0;  // initialize

				// Loop through possible next period states 
				// savings does not need to be computed, every single time, in the inner loop. 25/04/2014 MDN ****
				// *?#?*
				// Used consumption grid for couples  cashnet= cashS[cashInd]-consumC[consumInd]; Corrected. 12/12/2016 RM

	savings = cashS[cashInd] - consumS[consumInd]; // coh - consumption
	DisA = min(savings, AssetDisregardS); //Available disregardable savings added RM *?#?* 01/19
	for (rInd = 0; rInd < RDIM; rInd++)
	{
		DisI = min(rA[rInd] * savings + ySM[i][IInd][tInd + 1], IncDisregardS); //Available disregadable income added RM *?#?* 01/19

																				// *?#?* Differential tax treatment of singles and couples RM 01/2017
																				// Swapped to AfterTaxIncomeS from AfterTaxIncome
		for (hsIndN = 0; hsIndN < HSDIM; hsIndN++)
		{
			// *?#?*
			// the mecostshifter DOES need to be in the inner loop. In 2014 version multiplying whole medcostshifter
			// by zeta value --> shifting the mean medical expenditure as well as the variance. Should be using variance
			// to scale zeta. 12/12/2016 RM  *?#?* Updated RM 09/17 to allow for dependence on lagged health
			medcostshifter = hcSIntercept[i][hsInd][hsIndN][tInd + 1][IInd];
			// 2014 version:       
			// this medcostshifter does not need to be in the inner loop either. 25/04/2014 MDN ****
			// medcostshifter=hcSIntercept[i][hsIndN][tInd+1][IInd]+hcSSigma[i][hsIndN][tInd+1][IInd];
			for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
			{
				for (xiInd = 0; xiInd < XIDIM; xiInd++)
				{
					//*?#?*
					// Changed in line with medcostshifter change to preserve deterministic values 12/12/2016 RM  
					// Changed in line with note on model timing 08/17 RM  
					//  *?#?* Updated RM 09/17 to allow for dependence on lagged health -11/17 added modelperiod multipliers to income
					cashnet = savings - MODELPERIOD * exp((medcostshifter + hcSSigma[i][hsInd][hsIndN][tInd + 1][IInd] * (zetaA[zetaIndN] + xiA[xiInd]))); //savings after the realisation of medical shocks    
																																						   //Incorporate returns:
					cashnet = cashnet + MODELPERIOD * AfterTaxIncomeS(rA[rInd] * savings + (ySM[i][IInd][tInd + 1])); //*?#?* replaced savings 

					cashOnHand = max(cashnet - (DisI + DisA), cMinS) + DisI + DisA; //RM *?#?* 01/19 - Incorporate medically needy pathway to medicaid


					sum += hsProbSM[i][tInd][IInd][hsInd][hsIndN] * zetaProbM[zetaInd][zetaIndN] * rProbA[rInd] * xiProbA[xiInd] * Interpolation(&valueFunSM[i][tInd + 1][IInd][hsIndN][zetaIndN][0], cashS, cashOnHand, CASHDIM);
					// 2014 version:
					//  cashOnHand = max(savings-exp((medcostshifter*(zetaA[zetaIndN]+xiA[xiInd]))), cMinS); 
					//  sum+= hsProbSM[i][tInd][IInd][hsInd][hsIndN]*zetaProbM[zetaInd][zetaIndN]*rProbA[rInd]*xiProbA[xiInd]*Interpolation(&valueFunSM[i][tInd+1][IInd][hsIndN][zetaIndN][0], cashS, cashOnHand, CASHDIM);        
					// previous, inefficient, version ****
					// cashOnHand = max(cashA[cashInd]-consumA[consumInd]
					//            +AfterTaxIncome(rA[rInd]*(cashA[cashInd]-consumA[consumInd])
					//            +(yM[i][IInd][tInd+1]))-exp((hcSLogMean[i][hsIndN][tInd+1][IInd]
					//            +hcSSigma[i][hsIndN][tInd+1][IInd]*(zetaA[zetaIndN]+xiA[xiInd]))), cMin); 
					//sum+= hsProbSM[i][tInd][IInd][hsInd][hsIndN]*zetaProbM[zetaInd][zetaIndN]*rProbA[rInd]*xiProbA[xiInd]*Interpolation(&valueFunM[i][tInd+1][IInd][hsIndN][zetaIndN][0], cashA, cashOnHand, CASHDIM); 
				}
			}
		}
	} // end looping through possible next period states 

	  // valueM stores the utility for each possible choice of consumption    
	  //*?#?*  Change to incorporate new bequest matrix accounting for end of life costs & scrambling of asset grid in parallel 08/17
	  //*?#?* RM 01/18 removed time dimension from beqUSM as compute at each t

	return utilitySM[hsInd][consumInd] + beta * (1 - survivalProbSM[i][tInd][hsInd][IInd]) * bequestUSM[i][cashInd][IInd][hsInd][zetaInd][consumInd]
		+ beta * survivalProbSM[i][tInd][hsInd][IInd] * sum;
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// *?#?* Major edits to incorporate new timing conventions RM 08/17
// We now solve widow/er bequests first then optimal consumption
void GetRulesCouples(int iAssetsmin, int iAssetsmax, int* assetAssignments)
{
	int  tInd, cashInd, cashInd2, IInd, hsHInd, hsWInd, zetaInd, consumInd;
	double maximum = 0.0;     // used in maximization to record maximum
	int index = 0;            // used in maximization to record index of maximizer 
	double valueM[CONSUMDIM]; // intermediate value function, used in maximization 


	double* tempvec;
	int recsize = IDIM * HSDIM * HSDIM * ZETADIM * CASHDIM; // *?#?* Fixed size of the Dimension to include IDIM RM 03/2017
	tempvec = (double*)calloc(recsize, sizeof(double));

	if ((useMPI < 2) || (rank == (size - 1)))
		printf("Solving for COUPLES. \n ");
	fflush(stdout);

	// notice that all loops refer to today's state variables, except for the one for consumption
	for (tInd = (TDIMC - 1); tInd >= 0; tInd--) //  *?#?* WIFEAGEDIF deleted in keeping with new TDIM structure RM 01/2017
	{
		if ((useMPI < 2) || (rank == (size - 1))) printf("Widow(er) Bequests: Age=%d \n ", tInd * MODELPERIOD + TSTART); // *?#?* Added Model period to print correct ages RM 01/2017
																													 //First for every end of this period death we find the optimal allocation of bequest and left behind savings
		fflush(stdout);



		GetBeqRulesCouples(tInd, iAssetsmin, iAssetsmax, assetAssignments);
#if(MPI_COMMENT==2) //conditional compile on using openMP *?#?*- Added control sequence RM 11/17
#pragma omp barrier //wait until every processor has hit this point
#endif  //close on Openmp 
		if ((useMPI < 2) || (rank == (size - 1))) printf("Precompute Bequest Expectation: Age=%d \n ", tInd * MODELPERIOD + TSTART); // *?#?* Added Model period to print correct ages RM 1/2018
		fflush(stdout);

		//Precompute expected bequests for final member death 01/2018 RM:
		GetUtilityBeqUCM(bequestUCM, iAssetsmin, iAssetsmax, assetAssignments, tInd); // find utility from bequest matrix for one spouse death  //*?#?* scrambling of asset grid in parallel RM 01/18


		if ((useMPI < 2) || (rank == (size - 1))) printf("Consumption: Age=%d \n ", tInd * MODELPERIOD + TSTART); // *?#?* Added Model period to print correct ages RM 01/2017
		fflush(stdout);

		for (cashInd2 = iAssetsmin; cashInd2 < iAssetsmax; cashInd2++)
			// COH for (cashInd = 0; cashInd<CASHDIM; cashInd++) 
		{ // **** 04/2014 Couples did not appear to have been parallelized. Noticed commented out instruction above

			cashInd = assetAssignments[cashInd2]; // "Scramble" gridpoints across clusters.  JBJ:  5/30/14 *?#?* added RM 08/2017

			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
				{
					for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
					{
						for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
						{
							// maximization on each node
							maximum = -10000.0;  // maximum utility 
							index = 0;  // index of consumption giving maximum utility  


							for (consumInd = 0; consumInd < CONSUMDIM; consumInd++)
							{  // loop through possible consumption choice 


							   //if (consumS[consumInd] <= cashS[cashInd]) OLD VERSION
								if (consumC[consumInd] < cashC[cashInd] || fabs(consumC[consumInd] - cashC[cashInd]) < ABS_TOL) // *?#?* Added almost exact comparison. Old version above RM 01/2017
								{
									valueM[consumInd] = GetValueCouples(tInd, IInd, hsHInd, hsWInd, zetaInd, cashInd,
										consumInd);
									// maximization over all possible consumption choices 

									if (valueM[consumInd] > maximum)
									{
										maximum = valueM[consumInd];
										index = consumInd;
									}// maximization 
								}
								else  // consumption choice is bigger than available cash on hand 
								{
									break;
								}
							}// end loop through consumption grid 
							 // Record value function for this period and policy function    
							valueFunCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd] = maximum;
							consumFunCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd] = consumC[index];
							// BequestFunHM[TDIMC]: both die so savings go to other heirs 
							bequestFunCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd] = cashC[cashInd] - consumC[index];
						}// end loop through persistent health shock 
					}// end loop through health status for wife                
				}// end loop through health status for husband 
			} // end loop through permanent income    
		}// end loop through cash on hand  

		 // MPI-specific Code:  Merge output from different processors 
		if (useMPI == 2)
		{
			//Begin the automated commenting *?#?*- Added control sequence RM 03/17
			// *?#?* Changed to explicit pointers with all dimensions for readability RM 03/2017
			// *?#?* Removed widow/er bequest functions which are reduced inside function GetBeqRulesCouples RM 08/2017
#if(MPI_COMMENT==1)
			MPI_Allreduce(&valueFunCM[tInd][0][0][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
			copyit(&valueFunCM[tInd][0][0][0][0][0], tempvec, recsize);
			MPI_Allreduce(&bequestFunCM[tInd][0][0][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
			copyit(&bequestFunCM[tInd][0][0][0][0][0], tempvec, recsize);
			MPI_Allreduce(&consumFunCM[tInd][0][0][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
			copyit(&consumFunCM[tInd][0][0][0][0][0], tempvec, recsize);
#endif     //(MPI_COMMENT==1)
#if(MPI_COMMENT==2) //conditional compile on using openMP *?#?*- Added control sequence RM 11/17
#pragma omp barrier //wait until every processor has hit this point
#endif  //close on Openmp 

		}
	} // end loop through age 

	free(tempvec);
}

// *?#?* New & scrambling of asset grid in parallel 08/17
void GetBeqRulesCouples(int tInd, int iAssetsmin, int iAssetsmax, int* assetAssignments)
{
	int  cashInd, cashInd2, hsInd, zetaInd, bequestHInd, bequestWInd, indexH, indexW, IInd;
	double cashOnHand;
	double sumH, sumW, maximum;
	double valH[BEQUESTDIM], valW[BEQUESTDIM];
	double* tempvec2;
	int recsize2 = IDIM * HSDIM * ZETADIM * CASHDIM;
	tempvec2 = (double*)calloc(recsize2, sizeof(double));

	sumH = 0.0;  // initialize
	sumW = 0.0;  // initialize

				 /* *?#?* for each possibility (dead husband, dead wife)- we compute the optimal bequest.
				 These bequests occur as an immediate give away (i.e. death and death associated medical expenses are realised first)
				 so households cannot give all away to their children, file for bankruptcy and claim medicaid

				 we define these rules on the beggining of next period cash

				 Solving this way is effectively 2 stage budgeting*/


	for (cashInd2 = iAssetsmin; cashInd2 < iAssetsmax; cashInd2++)   // COH
	{
		cashInd = assetAssignments[cashInd2]; // "Scramble" gridpoints across clusters.  JBJ:  5/30/14 *?#?* added RM 08/2017



		for (IInd = 0; IInd < IDIM; IInd++) // PI
		{
			for (hsInd = 0; hsInd < HSDIM; hsInd++) // today's health
			{
				for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++) // today's persistent medex shock
				{
					// HUSBAND DIES FIRST for (bequestHInd = 0; bequestHInd<BEQUESTDIM; bequestHInd++) 

					// maximization on each node 
					maximum = -1000000.0;  // maximum utility 
					indexH = 0;           // Index of bequest giving maximum utility 

										  // loop through possible bequest choice 
					for (bequestHInd = 0; bequestHInd < BEQUESTDIM; bequestHInd++)
					{
						//With bequest defined as a fraction of CashOnHad no need to do the logical check
						cashOnHand = cashS[cashInd] - bequestHWM[cashInd][bequestHInd]; // coh - consumption

																						//Don't allow them to dodge the consumption floor
						if ((cashOnHand > cMinS + AssetDisregardS + IncDisregardS) || (fabs(cashOnHand - (cMinS + AssetDisregardS + IncDisregardS)) < ABS_TOL)) // *?#?* don't violate Cfloor, but can be exactly equal (implemented with tolerance) ammended 10/17 RM
																																							//RM *?#?* 01/19 - Incorporate medically needy pathway /disregards to the cash on hand constraint Note that if we don't do any loops default to 0
						{
							sumH = Interpolation(&valueFunSM[1][tInd + 1 - WIFEAGEDIF][IInd][hsInd][zetaInd][0], cashS, cashOnHand, CASHDIM);
							valH[bequestHInd] = sumH * omega + bequestUHWM[cashInd][bequestHInd]; // *?#?* Added Omega here RM 10/17



																								  // maximization over all possible consumption choices 
							if (maximum < valH[bequestHInd])
							{
								maximum = valH[bequestHInd];
								indexH = bequestHInd;
							} //maximization 
						}
						else //bequest choice involves giving away too many assets to violate the consumption floor
						{ //The beq grid is increasing so this will be true for any larger beq index
							break;
						}
					}// end loop through bequest grid 
					 // record value function for this period and policy function 
					 // *?#?*

					bequestFunHM[tInd][IInd][hsInd][zetaInd][cashInd] = bequestHWM[cashInd][indexH];

					// WIFE DIES FIRST for (bequestWInd = 0; bequestWInd<BEQUESTDIM; bequestWInd++) 

					// maximization on each node 
					maximum = -1000000.0;  // maximum utility 
					indexW = 0;           // Index of bequest giving maximum utility 

										  // loop through possible bequest choice 
					for (bequestWInd = 0; bequestWInd < BEQUESTDIM; bequestWInd++)
					{
						//With bequest defined as a fraction of CashOnHad no need to do the logical check
						cashOnHand = cashS[cashInd] - bequestHWM[cashInd][bequestWInd]; // coh - consumption
						if ((cashOnHand > cMinS + AssetDisregardS + IncDisregardS) || (fabs(cashOnHand - (cMinS + AssetDisregardS + IncDisregardS)) < ABS_TOL)) // *?#?* don't violate Cfloor, but can be exactly equal (implemented with tolerance) ammended 10/17 RM
																																							//RM *?#?* 01/19 - Incorporate medically needy pathway /disregards to the cash on hand constraint Note that if we don't do any loops default to 0
						{
							sumW = Interpolation(&valueFunSM[0][tInd + 1][IInd][hsInd][zetaInd][0], cashS, cashOnHand, CASHDIM);
							valW[bequestWInd] = sumW * omega + bequestUHWM[cashInd][bequestWInd]; // *?#?* Added Omega here RM 10/17

																								  // maximization over all possible consumption choices 
							if (maximum < valW[bequestWInd])
							{
								maximum = valW[bequestWInd];
								indexW = bequestWInd;
							} //if statement maximization
						}
						else //bequest choice involves giving away too many assets to violate the consumption floor
						{ //The beq grid is increasing so this will be true for any larger beq index
							break;
						}

					}// end loop through bequest grid 
					 // record value function for this period and policy function 
					 // *?#?*

					bequestFunWM[tInd][IInd][hsInd][zetaInd][cashInd] = bequestHWM[cashInd][indexW];


				}// end loop through persistent health shock        
			}// end loop through health status    
		}// end loop through permanent income    

	} // end loop for cash on hand 
	if (useMPI == 2)
	{
#if(MPI_COMMENT==1)
		MPI_Allreduce(&bequestFunHM[tInd][0][0][0][0], tempvec2, recsize2, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
		copyit(&bequestFunHM[tInd][0][0][0][0], tempvec2, recsize2);
		MPI_Allreduce(&bequestFunWM[tInd][0][0][0][0], tempvec2, recsize2, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
		copyit(&bequestFunWM[tInd][0][0][0][0], tempvec2, recsize2);
#endif     //(MPI_COMMENT==1)
	}
#if(MPI_COMMENT==2) //conditional compile on using openMP
#pragma omp barrier //wait until every processor has hit this point
#endif  //close on Openmp
	free(tempvec2);

}

// *?#?* Major edits to incorporate new timing conventions RM 08/17
double GetValueCouples(int tInd, int IInd, int hsHInd, int hsWInd, int zetaInd,
	int cashInd, int consumInd)
{
	int rInd, hsHIndN, hsWIndN, zetaIndN, xiInd;

	double cashnet, savings, medcostshifter, cashOnHand, beqcost, bequtil;
	double DisA, DisI;	//Intermediate- the household's disregardable income added 01/18 RM *?#?*

	double sumC = 0.0;          // expected value next period in case both couple members survive
	double sumH = 0.0;      // expected value next period in case husband dies
	double sumW = 0.0;      // expected value next period in case wife dies

							// There is an optimal bequest amount conditional on 
							// each consumption level for the couple while both alive.
							//*?#?* change to the timing of the budget constraint 08/17

	savings = cashC[cashInd] - consumC[consumInd]; // coh - consumption

												   /* *?#?*
												   2014 version had flipped the order of the loops so that bequests were interior. This Saved some overhead
												   recalculating savings, but caused the inccorect calculation of values & optimal bequest level.
												   This follows earlier versions, but avoids uncesseary recalculations    12/12/2016 RM
												   */

												   // HUSBAND DIES FIRST for (bequestHInd = 0; bequestHInd<BEQUESTDIM; bequestHInd++) 
												   //Set the disregards:
	DisA = min(savings, AssetDisregardS); //Available disregardable savings added RM *?#?* 01/19
	for (rInd = 0; rInd < RDIM; rInd++) // interest rate realization next period
	{
		DisI = min(rA[rInd] * savings + ySM[1][IInd][tInd + 1], IncDisregardS); //Available disregadable income added RM *?#?* 01/19


																				// loop through other possible next period states other than interest rate
		for (hsWIndN = 0; hsWIndN < HSDIM; hsWIndN++) // wife's health status
		{
			// *?#?*
			// the mecostshifter DOES need to be in the inner loop. In 2014 version multiplying whole medcostshifter
			// by zeta value --> shifting the mean medical expenditure as well as the variance. Should be using variance
			// to scale zeta. 12/12/2016 RM
			//Added death costs for the man 08/17 RM
			//  *?#?* Updated RM 09/17 to allow for dependence on lagged health
			medcostshifter = hcSIntercept[1][hsWInd][hsWIndN][tInd + 1 - WIFEAGEDIF][IInd] + laghealthIntercept[0][hsHInd] + deathcostsIntercept[0][IInd];
			// 2014 version:
			// medcostshifter=hcSIntercept[1][hsWIndN][tInd+1][IInd]+hcSSigma[1][hsWIndN][tInd+1][IInd];           
			for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
			{
				for (xiInd = 0; xiInd < XIDIM; xiInd++)
				{
					// *?#?*
					// Changed in line with change to medcostshifter    12/12/2016 RM
					// changes to timing convention 08/17 RM
					// *?#?* Differential tax treatment of singles and couples RM 01/2017
					//Switched AfterTaxIncome to AfterTaxIncomeS because single household after spouse dies
					// *?#?* Updated RM 09/17 to allow for dependence on lagged health 11/17 added 2 year adjustment to incme
					cashnet = savings - MODELPERIOD * exp((medcostshifter + (sqrt(pow(hcSSigma[1][hsWInd][hsWIndN][tInd + 1 - WIFEAGEDIF][IInd], 2.0) + laghealthVar[0][hsHInd] + deathcostsVar[0][IInd])) * (zetaA[zetaIndN] + xiA[xiInd]))); //savings after the realisation of medical shocks   
					cashnet = cashnet + MODELPERIOD * AfterTaxIncomeS(rA[rInd] * savings + (ySM[1][IInd][tInd + 1 - WIFEAGEDIF])); // savings before medex and gvt transfers 					//*?#?* replaced savings
																																   //Note that as in section 3.3 bequests must be .leq. savings carried forward, but subtract after returns from interest
					cashOnHand = max(cashnet - (DisI + DisA), cMinS) + DisI + DisA; //RM *?#?* 01/19 - Incorporate medically needy pathway to medicaid
																					//This is the cashOnHand from which we will remove bequests
																					//Because bequests are defined on the next period cash on hand we need to interpolate the bequest

					beqcost = Interpolation(&bequestFunHM[tInd][IInd][hsWIndN][zetaIndN][0], cashS,
						cashOnHand, CASHDIM);


					//Now subtract to leave true cashonhand for start of period as single


					cashOnHand = cashOnHand - beqcost;
					// evaluate the utility from this bequest
					bequtil = UBeqHW(beqcost);

					// 2014 version:    
					// cashOnHand = max(savings-exp((medcostshifter*(zetaA[zetaIndN]+xiA[xiInd]))), cMinS);
					/* cashOnHand = max(cashC[cashInd]-consumC[consumInd]
					+ AfterTaxIncome(rA[rInd]*(cashC[cashInd]-consumC[consumInd])+(yM[1][IInd][tInd+1]))
					-exp((hcSIntercept[1][hsWIndN][tInd+1][IInd]
					+hcSSigma[1][hsWIndN][tInd+1][IInd]*(zetaA[zetaIndN]+xiA[xiInd]))), cMinS); */


					// *?#?* 
					// Mistakenly interpolated on the state grid for couples cash,  but husband is dead and next period state grid is single cash  12/12/2016 RM
					// Using the wifeagediff to control for the difference in  01/2017 RM
					sumH += hsProbSM[1][tInd][IInd][hsWInd][hsWIndN] * zetaProbM[zetaInd][zetaIndN]
						* rProbA[rInd] * xiProbA[xiInd]
						* (Interpolation(&valueFunSM[1][tInd + 1 - WIFEAGEDIF][IInd][hsWIndN][zetaIndN][0], cashS,
							cashOnHand, CASHDIM) * omega + bequtil); // *?#?* Added Omega here RM 10/17



				}  // for (xiInd = 0; xiInd<XIDIM; xiInd++)
			} // for (zetaIndN = 0; zetaIndN<ZETADIM; zetaIndN++)
		} // for (hsHIndN = 0; hsHIndN<HSDIM; hsHIndN++)
	}// for (rInd = 0; rInd<RDIM; rInd++)
	 // Notice that bequestUHWM is constrained as COH TODAY-consumption today, as should be. 
	 // add utility of bequeathing to other heirs piece
	 // WIFE DIES FIRST for (bequestWInd = 0; bequestHInd<BEQUESTDIM; bequestHInd++) 
	DisA = min(savings, AssetDisregardS); //Available disregardable savings added RM *?#?* 01/19
	for (rInd = 0; rInd < RDIM; rInd++) // interest rate realization next period
	{
		DisI = min(rA[rInd] * savings + ySM[0][IInd][tInd + 1], IncDisregardS); //Available disregadable income added RM *?#?* 01/19
																				// loop through other next period states, besides interest rate
		for (hsHIndN = 0; hsHIndN < HSDIM; hsHIndN++)
		{
			// *?#?* 
			// Same change as in husband dies first  12/12/2016 RM & 08/17 RM
			// *?#?* Updated RM 09/17 to allow for dependence on lagged health
			medcostshifter = hcSIntercept[0][hsHInd][hsHIndN][tInd + 1][IInd] + laghealthIntercept[1][hsWInd] + deathcostsIntercept[1][IInd];
			// 2014 version:
			//medcostshifter=hcSIntercept[0][hsHIndN][tInd+1][IInd]+hcSSigma[0][hsHIndN][tInd+1][IInd];
			for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
			{
				for (xiInd = 0; xiInd < XIDIM; xiInd++)
				{
					// *?#?* 
					// Same change as in husband dies first  12/12/2016 RM
					//New timing convention 08/17
					// *?#?* Differential tax treatment of singles and couples RM 01/2017
					//Switched AfterTaxIncome to AfterTaxIncomeS because single household after spouse dies
					// *?#?* Updated RM 09/17 to allow for dependence on lagged health 11/17 added 2 year adjustment to income
					cashnet = savings - MODELPERIOD * exp(medcostshifter + (sqrt(pow(hcSSigma[0][hsHInd][hsHIndN][tInd + 1][IInd], 2.0) + laghealthVar[1][hsWInd] + deathcostsVar[1][IInd])) * (zetaA[zetaIndN] + xiA[xiInd])); // savings after last medex

					cashnet = cashnet + MODELPERIOD * AfterTaxIncomeS(rA[rInd] * savings + (ySM[0][IInd][tInd + 1])); //*?#?* replaced savings
					cashOnHand = max(cashnet - (DisI + DisA), cMinS) + DisI + DisA;

					//This is the cashOnHand from which we will remove bequests
					//Because bequests are defined on the next period cash on hand we need to interpolate the bequest

					beqcost = Interpolation(&bequestFunWM[tInd][IInd][hsHIndN][zetaIndN][0], cashS,
						cashOnHand, CASHDIM);


					//Now subtract to leave true cashonhand for start of period as single


					cashOnHand = cashOnHand - beqcost;
					// evaluate the utility from this bequest
					bequtil = UBeqHW(beqcost);


					sumW += hsProbSM[0][tInd][IInd][hsHInd][hsHIndN] * zetaProbM[zetaInd][zetaIndN]
						* rProbA[rInd] * xiProbA[xiInd]
						* (Interpolation(&valueFunSM[0][tInd + 1][IInd][hsHIndN][zetaIndN][0], cashS,
							cashOnHand, CASHDIM) * omega + bequtil); // *?#?* Added Omega here RM 10/17


																   //2014 version:
																   // maxW+=hsProbSM[0][tInd][IInd][hsHInd][hsHIndN]*zetaProbM[zetaInd][zetaIndN]
																   //*rProbA[rInd]*xiProbA[xiInd]
																   //         *Interpolation(&valueFunSM[0][tInd+1][IInd][hsHIndN][zetaIndN][0], cashC, 
																   //         cashOnHand-bequestHWM[cashInd][consumInd][bequestWInd], CASHDIM);

																   /* maxW+=hsProbCM[tInd][IInd][hsHInd][hsWInd][hsHIndN][HSDIM]
																   *zetaProbM[zetaInd][zetaIndN]*rProbA[rInd]*xiProbA[xiInd]
																   *Interpolation(&valueFunSM[0][tInd+1][IInd][hsHIndN][zetaIndN][0], cashC,
																   cashOnHand-bequestHWM[cashInd][consumInd][bequestWInd], CASHDIM); */

				}  // for (xiInd = 0; xiInd<XIDIM; xiInd++)
			} // for (zetaIndN = 0; zetaIndN<ZETADIM; zetaIndN++)
		} // for (hsHIndN = 0; hsHIndN<HSDIM; hsHIndN++)
	}// for (rInd = 0; rInd<RDIM; rInd++)
	DisA = min(savings, AssetDisregardC); //Available disregardable savings added RM *?#?* 01/19
	for (rInd = 0; rInd < RDIM; rInd++) // interest rate realization next period
	{
		DisI = min(rA[rInd] * savings + yCM[IInd][tInd + 1], IncDisregardC); //Available disregadable income added RM *?#?* 01/19

																			 // BOTH ALIVE NEXT PERIOD

																			 // bequestFunHM is the optimal choice of bequest giving consumption choice    
																			 // loop through other possible next period states 
		for (hsHIndN = 0; hsHIndN < HSDIM; hsHIndN++)
		{
			for (hsWIndN = 0; hsWIndN < HSDIM; hsWIndN++)
			{    // *?#?* 
				 // Same change as in husband dies first  12/12/2016 RM
				 // *?#?* Updated RM 09/17 to allow for dependence on lagged health
				medcostshifter = hcCIntercept[hsHInd][hsWInd][hsHIndN][hsWIndN][tInd + 1][IInd];

				// 2014 version:

				// medcostshifter=hcCIntercept[hsHIndN][hsWIndN][tInd+1][IInd]+hcCSigma[hsHIndN][hsWIndN][tInd+1][IInd];       
				for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
				{
					for (xiInd = 0; xiInd < XIDIM; xiInd++)
					{
						// *?#?* 
						// Same change as in husband dies first for medcostshifter  12/12/2016 RM
						//change to update timing and budget constraint 08/17 RM
						// *?#?* Differential tax treatment of singles and couples RM 01/2017
						//Switched AfterTaxIncome to AfterTaxIncomeC because couple with both spouses alive
						//medex before returns
						// *?#?* Updated RM 09/17 to allow for dependence on lagged health - 11/17 added 2 year adjustment to income
						cashnet = savings - MODELPERIOD * exp(medcostshifter + hcCSigma[hsHInd][hsWInd][hsHIndN][hsWIndN][tInd + 1][IInd] * (zetaA[zetaIndN] + xiA[xiInd]));
						cashnet = cashnet + MODELPERIOD * AfterTaxIncomeC(rA[rInd] * savings + (yCM[IInd][tInd + 1]));  //Add returns 
																														//*?#?* replaced savings
						cashOnHand = max(cashnet - (DisI + DisA), cMinC) + DisI + DisA; //RM *?#?* 01/19 - Incorporate medically needy pathway to medicaid

																						// 2014 version:  
																						// cashOnHand = max(savings-exp((medcostshifter*(zetaA[zetaIndN]+xiA[xiInd]))), cMinC);
																						/*cashOnHand = max(cashC[cashInd]-consumC[consumInd]
																						+AfterTaxIncome(rA[rInd]*(cashC[cashInd]-consumC[consumInd])
																						+(yM[2][IInd][tInd+1]))-exp( (hcCIntercept[hsHIndN][hsWIndN][tInd+1][IInd]
																						+hcCSigma[hsHIndN][hsWIndN][tInd+1][IInd]*(zetaA[zetaIndN]+xiA[xiInd]))), cMinC); */
						sumC += hsProbCM[0][tInd][IInd][hsHInd][hsHIndN] * hsProbCM[1][tInd][IInd][hsWInd][hsWIndN]
							* zetaProbM[zetaInd][zetaIndN] * rProbA[rInd] * xiProbA[xiInd]
							* Interpolation(&valueFunCM[tInd + 1][IInd][hsHIndN][hsWIndN][zetaIndN][0],
								cashC, cashOnHand, CASHDIM);





						/*sumC+= hsProbCM[tInd][IInd][hsHInd][hsWInd][hsHIndN][hsWIndN]
						*zetaProbM[zetaInd][zetaIndN]*rProbA[rInd]*xiProbA[xiInd]
						*Interpolation(&valueFunCM[tInd+1][IInd][hsHIndN][hsWIndN][zetaIndN][0],
						cashC, cashOnHand, CASHDIM); */
					}
				}
			}
		}
	}// end looping through possible next period's interest rate

	 // *?#?* added omega (controls the weight on surviving spouse) multiplying continuation values
	 // for spouse survival  RM 01/2017
	 // *?#?* fixed using survival probabilities for couples   
	 // valueM stores the utility for each possible choice of consumption 
	 //*?#?* fixed using survival probabilities for couples - Incorporated changes to the calculation of death expenses and bequest costs  
	return utilityCM[hsHInd][hsWInd][consumInd] + beta * (
		(1 - survivalProbCM[0][tInd][hsHInd][IInd]) * (1 - survivalProbCM[1][tInd][hsWInd][IInd]) * bequestUCM[cashInd][IInd][hsHInd][hsWInd][zetaInd][consumInd]
		+ survivalProbCM[0][tInd][hsHInd][IInd] * survivalProbCM[1][tInd][hsWInd][IInd] * sumC
		+ (1 - survivalProbCM[0][tInd][hsHInd][IInd]) * survivalProbCM[1][tInd][hsWInd][IInd] * sumH
		+ survivalProbCM[0][tInd][hsHInd][IInd] * (1 - survivalProbCM[1][tInd][hsWInd][IInd]) * sumW); // *?#?* Removed Omega here RM 10/17, removed tind beqUCM here RM 01/18
																									 /* Old version in 2014 code
																									 return utilityCM[hsHInd][hsWInd][consumInd] + beta*(
																									 (1-survivalProbSM[0][tInd][hsHInd][IInd])*(1-survivalProbSM[1][tInd][hsWInd][IInd])*bequestUCM[cashInd][consumInd]
																									 + survivalProbSM[0][tInd][hsHInd][IInd]*survivalProbSM[1][tInd][hsWInd][IInd]*sumC
																									 + (1-survivalProbSM[0][tInd][hsHInd][IInd])*survivalProbSM[1][tInd][hsWInd][IInd]*sumH
																									 + survivalProbSM[0][tInd][hsHInd][IInd]*(1-survivalProbSM[1][tInd][hsWInd][IInd])*sumW);
																									 */
}



//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/* Simulation of assets sequence
Subroutines needed:
1 dimensional interpolation
Discretization into markov chain
*/
/* This works similarly to the first version of the simulation code. Logic is as follows:
First, if the nomortallity option is selected for each household replace all marital statuses with original.
This accounts for differential lifespans of men and women.
For each household if initially dead or couple, fill with 0s. Skip.
Set up initial values. If initially a couple start solving the couple problem. Once either all members
or one member dies. Stop solving couple problem (break out of loop).
If initially single, update the singles index (sex) and start solving forward from the index. If they are the
surviving member of a couple- the couples part of the code will have updated this.
When single person dies, update the deceased index (if both die couples code also does this)  and loop forward
filling in deceased values. Works on the basis that if the initial value of the counter in a for loop violates
the stopping condition it isn't executed.

This minimises the amount of repeat code to maintain and minimises logic checks. - *?#?* Created based on older
versions of singles code RM 01/2017
*?#?* Updated for compatible index between GAUSS Health Status RM 06/2017
*?#?* Updated to new timing convention & incorporated deathcosts! RM 08/17
*?#?* Modified deathcosts & lagged health RM 09/17
*?#?* Modified initial conditions RM 11/17
*/
void simulation(GMatrix zetacdfsim96Ptr, GMatrix PIsim96Ptr, GMatrix agesim96Ptr, GMatrix incomesim96Ptr, GMatrix assetsim96Ptr,
	double** cohsimMat, double** assetsimMat, double** netIncomesimMat,
	double** consumptionsimMat, double** healthsimhMat, double** healthsimwMat,
	double** marstatsimMat, double** xicdfsimMat, double** epsiloncdfsimMat,
	double** healthcostsimMat, double** zetaindexsimMat, double** zetasimMat,
	double** xiindexsimMat, double** xisimMat, double** MedicaidsimMat,
	double* rorsim, double** beqsimMat, double** marstatsim2Mat,
	double** transfersimMat, double** initIndexsimMat, int iSimmin, int iSimmax) // JBJ: 7/11/08, 7/23/08, 5/6/09, 6/11/09 

{
	int personInd, yearInd, yearInd2, yearInd3, tInd, zetaInd_before, hsInd, hsHInd, hsWInd, laghsInd, laghsHInd, laghsWInd, zetaInd, xiInd, PIInd1, PIInd2, justdead;
	double weight;          // Contains weight used to interpolate on PI dimension. 
	struct result result1;  // return of GetLocation, for interpolation

	double coh, coh_pre_transfer, assets, consumption, grossIncome, netIncome, xi, zeta, epsilon, deathcosts, deathVar1, deathVar2, beqwidow, transfersim;
	double healthCost, Medicaid;      // health costs, not their logs.  JBJ:  7/23/08 
	int sex, age96;                   // What is Medicaid? ****
	int cohInd; // RM 11/17
	double DisA, DisI;	//Intermediate- the household's disregardable income added 01/18 RM *?#?*

						//double *tempvec, *tempV;

	int recsize = nsims;

	/* *?#?* Commented out RM 09/17 tempvec = (double *)calloc(recsize, sizeof(double));
	*?#?* tempV = (double *)calloc(recsize, sizeof(double)); */

	/* timing: at the begining of each period, know coh, marital status, age, health statues, PI, zeta*/
	if (switchMor == 0) /* no mortality risk*/
	{
		for (personInd = iSimmin; personInd < iSimmax; personInd++)
		{
			age96 = (int)floor(rounder + agesim96Ptr.data[personInd]);
			for (yearInd = 1; yearInd < TDimSims + 1; yearInd++)
			{
				if ((age96 + yearInd * MODELPERIOD) < (TSTART + TDIMC * MODELPERIOD)) /* Not too old for model as a couple or single man*/
				{
					marstatsimMat[yearInd][personInd] = marstatsimMat[yearInd - 1][personInd];
				}  /* Alive, for sure */
				else if ((marstatsimMat[yearInd][personInd] == 2) && ((age96 + yearInd * MODELPERIOD) >= (TSTART + TDIMC * MODELPERIOD)) && ((age96 + yearInd * MODELPERIOD) < (TSTART + TDIMS * MODELPERIOD)))
				{
					marstatsimMat[yearInd][personInd] = 2;  //Must be a woman

															/* A Single Woman who gets to live longer due to longer lifespans is still not too old */

				}
				else
				{
					marstatsimMat[yearInd][personInd] = 0;
				}  /* Too old for model, treat as dead */

			}
		}
	}



	printf("iSimmin=%d iSimmax=%d \n", iSimmin, iSimmax);
	fflush(stdout);

	/* for(personInd=150016; personInd<150017; personInd++) */
	for (personInd = iSimmin; personInd < iSimmax; personInd++)
	{
		justdead = 0;


		if ((switchCouple == 0) && (marstatsimMat[0][personInd] == 3))

		{
			for (yearInd = 0; yearInd < TDimSims; yearInd++)
			{
				marstatsimMat[yearInd][personInd] = 0;
				healthcostsimMat[yearInd][personInd] = -1e5;
				MedicaidsimMat[yearInd][personInd] = -1e5; // JBJ:  7/23/08 
				zetaindexsimMat[yearInd][personInd] = -1;   // JBJ:  7/11/08  
				zetasimMat[yearInd][personInd] = -1e5; // JBJ:  7/11/08 
				xiindexsimMat[yearInd][personInd] = -1;   // JBJ:  7/23/08  
				xisimMat[yearInd][personInd] = -1e5; // JBJ:  7/23/08 
				consumptionsimMat[yearInd][personInd] = -1e5;
				beqsimMat[yearInd][personInd] = -1e5;
				cohsimMat[yearInd][personInd] = -1e5;
				assetsimMat[yearInd][personInd] = -1e5;
				netIncomesimMat[yearInd][personInd] = -1e5;
				transfersimMat[yearInd][personInd] = -1e5; // JBJ:  6/11/09 
			}
			continue; /* skips the rest of the loop and onto next person*/

		}


		/* Initialize zetaindexsimMat[0][personInd].  GAUSS provides a draw
		from a U[0,1] distribution, which is combined with the invariant cdf
		to produce an index on the discretized chain.
		Also simulate initial draws of xiindexsim and xi.
		Next 10 lines modified by JBJ:  7/11/08, 7/23/08
		*/
		zeta = zetacdfsim96Ptr.data[personInd];
		zetaInd = GetLocation(&zetaInvcdf[0], zeta, ZETADIM + 1).Ind1;
		zeta = zetaA[zetaInd];  /* actual value of zeta */
		xi = xicdfsimMat[0][personInd];
		xiInd = GetLocation(&xiProbAcdf[0], xi, XIDIM + 1).Ind1;
		xi = xiA[xiInd];  /* actual value of xi */
		zetaindexsimMat[0][personInd] = zetaInd;
		zetasimMat[0][personInd] = zeta;
		xiindexsimMat[0][personInd] = xiInd;
		xisimMat[0][personInd] = xi;
		// *?#?* RM 11/17:
		//Record initial value of assets and cash
		//
		//Pick up initial values of assets and gross income
		assets = assetsim96Ptr.data[personInd];
		//Incorporate asset return in year 0
		grossIncome = incomesim96Ptr.data[personInd] + rorsim[0] * assetsim96Ptr.data[personInd];

		///due to diffierential grids for couples and singles and health statuses (plural) for couples we perform this seperately for singles and couples  
		//next 25 lines added RM 11/17 *?#?* -in spirit of AER code. Also adjust income for period length
		if ((marstatsimMat[0][personInd] == 3)) //Couple case
		{
			netIncome = MODELPERIOD * AfterTaxIncomeC(grossIncome);
			coh_pre_transfer = assets + netIncome;
			DisA = min(assets, AssetDisregardC);
			DisI = min(grossIncome, IncDisregardC); //collect the correct disregards RM 01/19 *?#?*
			coh = max(coh_pre_transfer - (DisI + DisA), cMinC) + DisI + DisA;

			cohsimMat[0][personInd] = coh;
			transfersimMat[0][personInd] = coh - coh_pre_transfer; //Still correct
																   //use couples cashgrids
			result1 = GetLocation(cashC, coh, CASHDIM);  //  Find index of closest asset gridpoint:  cricri, moved JBJ 8/15/12 -copied from AER code RM 07/17  
			cohInd = result1.Ind1; //store
		}
		else if ((marstatsimMat[0][personInd] == 1) || (marstatsimMat[0][personInd] == 2)) //Singles case
		{
			netIncome = MODELPERIOD * AfterTaxIncomeS(grossIncome);
			coh_pre_transfer = assets + netIncome;
			DisA = min(assets, AssetDisregardS);
			DisI = min(grossIncome, IncDisregardS); //collect the correct disregards RM 01/19 *?#?*
			coh = max(coh_pre_transfer - (DisI + DisA), cMinS) + DisI + DisA;

			cohsimMat[0][personInd] = coh;
			transfersimMat[0][personInd] = coh - coh_pre_transfer; //Still correct
																   //use singles cashgrids
			result1 = GetLocation(cashS, coh, CASHDIM);  //  Find index of closest asset gridpoint:  cricri, moved JBJ 8/15/12 -copied from AER code RM 07/17  
			cohInd = result1.Ind1;
		}
		/* To interpolate along PI dimension, need to find indexes that this point
		lies between and distance to each index. */
		result1 = GetLocation(IncomeA, PIsim96Ptr.data[personInd], IDIM);
		PIInd1 = result1.Ind1;
		weight = result1.weight;
		PIInd2 = PIInd1 + 1;

		age96 = ((int)floor(rounder + agesim96Ptr.data[personInd]) - TSTART) / MODELPERIOD; //Divide by modelperiod
																							//e.g. age96=70-64=6, but would be tind 3 with 2 year  periods
																							//age96 is now age in modelperiods at 96

																							/* timing for year 0:
																							marstatsimMat[0]->healthsimhMat[0], healthsimwMat[0], zetaindexsimMat[0],
																							cohsimMat[0]->consumptionsimMat[0]
																							*/
																							//Store the individual's initial conditions

																							//Taken from AER paper with modification *?#?* RM 11/17 
																							// Record a bunch of state indices for compensating differential calculations
		initIndexsimMat[0][personInd] = marstatsimMat[0][personInd]; // JBJ:  04/17/13
		initIndexsimMat[1][personInd] = age96 + 1;                     // JBJ:  04/17/13  C -> GAUSS indexing
		initIndexsimMat[2][personInd] = PIInd1 + 1;                     // JBJ:  04/17/13  C -> GAUSS indexing
		if (marstatsimMat[0][personInd] == 1)                          // JBJ:  04/17/13  
		{
			initIndexsimMat[3][personInd] = healthsimhMat[0][personInd];
			initIndexsimMat[4][personInd] = -1e5; //no spouse 
		}
		else if (marstatsimMat[0][personInd] == 2)                          // JBJ:  04/17/13  
		{
			initIndexsimMat[4][personInd] = healthsimwMat[0][personInd];
			initIndexsimMat[3][personInd] = -1e5; //no spouse
		}
		else if (marstatsimMat[0][personInd] == 3) //couple store both
		{
			initIndexsimMat[3][personInd] = healthsimhMat[0][personInd];
			initIndexsimMat[4][personInd] = healthsimwMat[0][personInd];
		}
		initIndexsimMat[5][personInd] = zetaInd + 1;                   // JBJ:  04/17/13  C -> GAUSS indexing
		initIndexsimMat[6][personInd] = xiInd + 1;                     // JBJ:  04/17/13  C -> GAUSS indexing
		initIndexsimMat[7][personInd] = cohInd + 1;                      // JBJ:  04/17/13  C -> GAUSS indexing
																		 //Store the original values of netIncome and assets calculated in C *?#?* Added by RM 11/17
		netIncomesimMat[0][personInd] = netIncome; //This is doubled above;
		assetsimMat[0][personInd] = assets;

		yearInd = 0;
		yearInd2 = TDimSims + 1; //If married this will be changed (otherwise auto skips loops)
		yearInd3 = TDimSims + 1; //If alive this will be changed (otherwise auto skips loops)
		tInd = age96 + yearInd;  /* age in model periods*/

								 /* Decide gender by looking at marital status ******* */
								 /* in beq10.gau, 1->male, 2->female */

								 /* AT THE MOMENT THE CODE ASSUMES THAT THE IF YOU ARE A SINGLE MAN WE HAVE MEANINGFUL DATA IN
								 THE MATRIX FOR HUSBAND HEALTH STATUS, BUT IGNORE THE WIFE VALUE. VICE VERSA FOR SINGLE WOMEN.
								 FOR MARRIED HOUSEHOLDS WE ASSUME THAT THERE IS INFO IN BOTH */

								 /*TO AVOID EXCESS IF STATEMENTS WE CONSTRUCT  COH OUTSIDE THE IFS, BUT INTERPOLATE INSIDE
								 THE IFS

								 Inside construct the interpolated consumption.*/
								 //Cash on hand no longer constructed here // RM 11/17
								 //*?#?* Added by RM 08/17 - set in the first death case and then reset each loop through.
		deathcosts = 0.0;
		deathVar1 = 0.0;
		deathVar2 = 0.0;

		/* **************************************************************************************** */
		/* Decide whether it is a couple or single case by looking at marital status */
		/* in beq10.gau, 1-> male, 2->wife, 3->used to couple */

		if ((marstatsimMat[0][personInd] == 3))
		{

			hsHInd = (int)floor(rounder + healthsimhMat[yearInd][personInd]) - 1;  // Gauss uses 1,2,3 indexing     
			hsWInd = (int)floor(rounder + healthsimwMat[yearInd][personInd]) - 1;  // Gauss uses 1,2,3 indexing     

			sex = 2; /*couple*/

					 // Interpolate- couples function and states. Couple grids.

			consumption = Interpolation(&consumFunCM[yearInd][PIInd1][hsHInd][hsWInd][zetaInd][0],
				cashC, coh, CASHDIM) * weight
				+ Interpolation(&consumFunCM[yearInd][PIInd2][hsHInd][hsWInd][zetaInd][0],
					cashC, coh, CASHDIM) * (1 - weight);

			/* Store the value of consumption */

			consumptionsimMat[yearInd][personInd] = consumption;

			//Start looping forward over Calendar year - will break if spouse dies so that we
			// can combine singles code and remaining after death code in a simple way that
			//a) eliminates unecessary if (once I know you're dead I don't check against spouse deaths 
			// or resurection)
			//b) Minimises code to be maintained
			//Cost is overhead on for statement (at most 3 times) vs all of these checks. Trade off is bottlenecks
			// in each person vs quicker per person- we should be parallelising across individuals instead 
			//of within people

			for (yearInd = 1; yearInd < TDimSims + 1; yearInd++)  /*calendar year*/
			{

				// Updated death costs to have lagged health status (use the fact that health stat hasn't updated)
				if (marstatsimMat[yearInd][personInd] == 2) //Single- partner must have died --NOTE: ERIC ORDERING AND JOHN ORDERING ARE NOT THE SAME IN STATA AND GAUSS
				{ //Changed marstatsim to be compatible with GAUSS *?#?* RM 11/17
					sex = 1; /* female */

							 // Single households- we will loop forwad with yearInd2 later:
					yearInd2 = yearInd; /*Store most recent year */

										//Last year's indexes are still all stored, only year has roled on once- Pull the correct bequest

										//No longer pull the bequest index here because we do not have the up to date state variables
					justdead = 1;
					deathcosts = deathcostsIntercept[0][PIInd1] * weight + deathcostsIntercept[0][PIInd2] * (1 - weight) + laghealthIntercept[0][hsHInd];
					deathVar1 = deathcostsVar[0][PIInd1] + laghealthVar[0][hsHInd];
					deathVar2 = deathcostsVar[0][PIInd2] + laghealthVar[0][hsHInd];
					//Added to pick up for the lagged household health status in singles loop RM 09/17
					hsInd = hsWInd;
					/* beqsimMat[yearInd][personInd]  =Interpolation(&bequestFunHM[tInd-1][PIInd1][hsHInd][hsWInd][zetaInd][0],
					cashC, coh, CASHDIM)*weight
					+ Interpolation(&bequestFunHM[tInd-1][PIInd1][hsHInd][hsWInd][zetaInd][0],
					cashC, coh, CASHDIM)*(1-weight);*/
					age96 = age96 - WIFEAGEDIF; //This is definied in model periods. Age96 is defined in model periods.
												//So adjust this here to give surviving wife's age
					break;
				} //female if
				else if (marstatsimMat[yearInd][personInd] == 1) //Single- partner must have died - //Changed marstatsim to be compatible with GAUSS *?#?* RM 11/17
				{
					sex = 0; /* male */

							 // Single households- we will loop forwad with yearInd2 later:
					yearInd2 = yearInd; /*Store most recent year */
										//Last year's indexes are still all stored, only year has roled on once- Pull the correct bequest
					justdead = 1;
					deathcosts = deathcostsIntercept[1][PIInd1] * weight + deathcostsIntercept[1][PIInd2] * (1 - weight) + laghealthIntercept[1][hsWInd];
					deathVar1 = deathcostsVar[1][PIInd1] + laghealthVar[1][hsWInd];
					deathVar2 = deathcostsVar[1][PIInd2] + laghealthVar[1][hsWInd];
					//Added to pick up for the lagged household health status in singles loop RM 09/17
					hsInd = hsHInd;
					/*
					beqsimMat[yearInd][personInd]  =Interpolation(&bequestFunWM[tInd-1][PIInd1][hsHInd][hsWInd][zetaInd][0],
					cashC, coh, CASHDIM)*weight
					+ Interpolation(&bequestFunWM[tInd-1][PIInd1][hsHInd][hsWInd][zetaInd][0],
					cashC, coh, CASHDIM)*(1-weight); */
					break; /* drop out of the loop on married couples */
				} //Male if
				else if (marstatsimMat[yearInd][personInd] == 0) /*dead people- fill in*/
				{
					/* household members all dead */
					//Major changes to incorporate death costs 08/17 RM *?#?*
					//This is a couple that must have died
					zetaInd_before = zetaInd; //Added 11/17 RM

					justdead = 1;
					epsilon = epsiloncdfsimMat[yearInd][personInd];
					zetaInd = GetLocation(&zetaProbMcdf[zetaInd_before][0], epsilon, ZETADIM + 1).Ind1;
					zeta = zetaA[zetaInd];  /* actual value of zeta */
					xi = xicdfsimMat[yearInd][personInd];
					xiInd = GetLocation(&xiProbAcdf[0], xi, XIDIM + 1).Ind1;
					xi = xiA[xiInd];  /* actual value of xi */
					zetaindexsimMat[yearInd][personInd] = zetaInd;
					zetasimMat[yearInd][personInd] = zeta;
					xiindexsimMat[yearInd][personInd] = xiInd;
					xisimMat[yearInd][personInd] = xi;
					//here we just subtract it whereas when a single member dies we add it prior to exponenting
					//Notice a key feature is that we haven't updated the health index yet so this is still last periods
					deathcosts = MODELPERIOD * exp(deathcostsFinalMemberC[tInd][PIInd1][hsHInd][hsWInd][zetaInd][xiInd] * weight +
						deathcostsFinalMemberC[tInd][PIInd2][hsHInd][hsWInd][zetaInd][xiInd] * (1 - weight));

					// Dead households- we will loop forwad with yearInd3 later:
					yearInd3 = yearInd;
					break; //Exit the couple section
				} //Dead
				else
				{ //Both partners still alive!

					tInd = age96 + yearInd; /* age*/
											/*Need to pick up the new values for stochastic process */

											/* zeta=rhoHc*zetaindexsimMat[yearInd][personInd]+epsilon;
											Zeta and xi are discretized into Markov chains.  Epsilon and xi are
											U[0,1] random variables that are combined with the chains' cdfs to
											produce discrete-valued draws.
											Write zeta and xi's index values into zetaindexsimMat, xiindexsimMat
											Next 10 lines modified by JBJ:  7/11/08, 7/23/08
											*/
					zetaInd_before = zetaInd; //Added 11/17 RM
					epsilon = epsiloncdfsimMat[yearInd][personInd];
					zetaInd = GetLocation(&zetaProbMcdf[zetaInd_before][0], epsilon, ZETADIM + 1).Ind1;
					zeta = zetaA[zetaInd];  /* actual value of zeta */
					xi = xicdfsimMat[yearInd][personInd];
					xiInd = GetLocation(&xiProbAcdf[0], xi, XIDIM + 1).Ind1;
					xi = xiA[xiInd];  /* actual value of xi */
					zetaindexsimMat[yearInd][personInd] = zetaInd;
					zetasimMat[yearInd][personInd] = zeta;
					xiindexsimMat[yearInd][personInd] = xiInd;
					xisimMat[yearInd][personInd] = xi;

					/*Get the indexes for health status */

					//Pick up the lagged values before we update to this period
					laghsHInd = hsHInd;
					laghsWInd = hsWInd;


					hsHInd = (int)floor(rounder + healthsimhMat[yearInd][personInd]) - 1;  // Gauss uses 1,2,3 indexing     
					hsWInd = (int)floor(rounder + healthsimwMat[yearInd][personInd]) - 1;  // Gauss uses 1,2,3 indexing     

																						   /* need to interpolate over PI to get health cost intercept and variance.
																						   Using renamed health costs*/
					healthCost = MODELPERIOD * exp((hcCIntercept[laghsHInd][laghsWInd][hsHInd][hsWInd][tInd][PIInd1] * weight
						+ hcCIntercept[laghsHInd][laghsWInd][hsHInd][hsWInd][tInd][PIInd2] * (1 - weight))
						+ (hcCSigma[laghsHInd][laghsWInd][hsHInd][hsWInd][tInd][PIInd1] * weight
							+ hcCSigma[laghsHInd][laghsWInd][hsHInd][hsWInd][tInd][PIInd2] * (1 - weight)) * (zeta + xi));

					/* Calculate net after tax income for realized interest rate shock */
					/* Need to interpolate over PI to get before tax income  */
					//*?#?* added healthcost subtraction to assets 08/17
					grossIncome = rorsim[yearInd] * (cohsimMat[yearInd - 1][personInd]
						- consumptionsimMat[yearInd - 1][personInd])
						+ yCM[PIInd1][tInd] * weight + yCM[PIInd2][tInd] * (1 - weight); //*?#?* replaced savings 05/18
					netIncome = MODELPERIOD * AfterTaxIncomeC(grossIncome);
					// *?#?* Differential tax treatment of singles and couples RM 01/2017

					// update assets and COH
					// Next 20 lines updated by JBJ 4/18

					assets = cohsimMat[yearInd - 1][personInd] - consumptionsimMat[yearInd - 1][personInd];
					coh_pre_transfer = assets + netIncome - healthCost;
					DisA = min(assets, AssetDisregardC);
					DisI = min(grossIncome, IncDisregardC); //collect the correct disregards RM 01/19 *?#?*
					coh = max(coh_pre_transfer - (DisA + DisI), cMinC) + DisA + DisI;
					Medicaid = 0.0;

					//*?#?* updated due to new timing convention - replacing healthcost and assets in loop RM 08/17 Fixed 11/17 Adjusted for disregard RM 01/19 *?#?*
					if (healthCost > assets + netIncome - DisA - DisI)     // Code in Medicaid -this check is if h}ealthCost>coh_t-1-con_t-1 
					{
						Medicaid = healthCost - (assets + netIncome - DisA - DisI);  //Calculate gap /*changed RM 08/18*/ Adjusted for disregard RM 01/19 *?#?*
					}

					//*?#?* Reorderd RM 22/05/18 - UPdated in line with new wequations 31/05/18

					transfersim = max((coh - DisA - DisI) - (coh_pre_transfer - DisA - DisI), 0.0); //Updated for disregards RM 01/19 *?#?*
					Medicaid = min(Medicaid, transfersim);
					healthCost = healthCost - Medicaid;
					healthcostsimMat[yearInd][personInd] = healthCost;
					transfersimMat[yearInd][personInd] = transfersim;
					MedicaidsimMat[yearInd][personInd] = Medicaid;
					netIncomesimMat[yearInd][personInd] = netIncome;
					assetsimMat[yearInd][personInd] = assets;
					cohsimMat[yearInd][personInd] = coh;

					// To get consumption function, interpolate over PI and COH 

					consumption = Interpolation(&consumFunCM[tInd][PIInd1][hsHInd][hsWInd][zetaInd][0],
						cashC, coh, CASHDIM) * weight
						+ Interpolation(&consumFunCM[tInd][PIInd2][hsHInd][hsWInd][zetaInd][0],
							cashC, coh, CASHDIM) * (1 - weight);

					consumptionsimMat[yearInd][personInd] = consumption;

				} //Both alive still
				marstatsim2Mat[yearInd][personInd] = marstatsimMat[yearInd][personInd]; // JBJ:  5/6/09

			} //The year through time for couples
		} /* original if on couples*/
		else if (marstatsimMat[yearInd][personInd] == 1) /* never in a couple, originally single male*/
		{
			sex = 0; /* male */
			hsInd = (int)floor(rounder + healthsimhMat[yearInd][personInd]) - 1;  // Gauss uses 1,2,3 indexing     
			consumption = Interpolation(&consumFunSM[sex][tInd][PIInd1][hsInd][zetaInd][0],
				cashS, coh, CASHDIM) * weight
				+ Interpolation(&consumFunSM[sex][tInd][PIInd2][hsInd][zetaInd][0],
					cashS, coh, CASHDIM) * (1 - weight);
			consumptionsimMat[yearInd][personInd] = consumption;
			yearInd2 = 1; /*Use this as an initial condition to loop forward */
		}
		else //Don't need to check as only other remaining option if (marstatsimMat[yearInd][personInd]==2) /* never in a couple, originally single female*/
		{
			sex = 1;       /*female */
			hsInd = (int)floor(rounder + healthsimwMat[yearInd][personInd]) - 1;  // Gauss uses 1,2,3 indexing
			consumption = Interpolation(&consumFunSM[sex][tInd][PIInd1][hsInd][zetaInd][0],
				cashS, coh, CASHDIM) * weight
				+ Interpolation(&consumFunSM[sex][tInd][PIInd2][hsInd][zetaInd][0],
					cashS, coh, CASHDIM) * (1 - weight);
			consumptionsimMat[yearInd][personInd] = consumption;
			yearInd2 = 1; /*Use this as an initial condition to loop forward */
		}


		/*Now loop forward using yearInd2, that's singles or previously coupled singles */
		for (yearInd = yearInd2; yearInd < TDimSims + 1; yearInd++)  /*calendar year-note skipped if never single*/
		{
			if (marstatsimMat[yearInd][personInd] == 0) /*dead people- fill in*/
			{
				/* household members all dead */

				//Major changes to incorporate death costs 08/17 RM *?#?*
				//This is a single that must have died
				justdead = 1;
				epsilon = epsiloncdfsimMat[yearInd][personInd];
				zetaInd_before = zetaInd; //Added 11/17 RM
				zetaInd = GetLocation(&zetaProbMcdf[zetaInd_before][0], epsilon, ZETADIM + 1).Ind1;
				zeta = zetaA[zetaInd];  /* actual value of zeta */
				xi = xicdfsimMat[yearInd][personInd];
				xiInd = GetLocation(&xiProbAcdf[0], xi, XIDIM + 1).Ind1;
				xi = xiA[xiInd];  /* actual value of xi */
				zetaindexsimMat[yearInd][personInd] = zetaInd;
				zetasimMat[yearInd][personInd] = zeta;
				xiindexsimMat[yearInd][personInd] = xiInd;
				xisimMat[yearInd][personInd] = xi;
				//Notice a key feature is that we haven't updated the health index yet so this is still last periods
				deathcosts = MODELPERIOD * exp(deathcostsFinalMemberS[sex][tInd][PIInd1][hsInd][zetaInd][xiInd] * weight +
					deathcostsFinalMemberS[sex][tInd][PIInd2][hsInd][zetaInd][xiInd] * (1 - weight));

				// Dead households- we will loop forwad with yearInd3 later:
				yearInd3 = yearInd;
				break; //Exit the alive singles section
			}
			else /* Still Single & not dead! */
			{

				zetaInd_before = zetaInd; //Edited 11/17 RM
				tInd = age96 + yearInd; /* age-assume that the matrix for starting values  */

										/* Using the fact that we already have sex as an integer for man or woman use integer arithmetic to pick up
										the correct indicator */
										//Pick up lags
				laghsInd = hsInd;
				hsInd = (int)floor(rounder + healthsimhMat[yearInd][personInd]) * (1 - sex) +
					sex * (int)floor(rounder + healthsimwMat[yearInd][personInd]) - 1;  // Gauss uses 1,2,3 indexing;

																						/* zeta=rhoHc*zetaindexsimMat[yearInd][personInd]+epsilon;
																						Zeta and xi are discretized into Markov chains.  Epsilon and xi are
																						U[0,1] random variables that are combined with the chains' cdfs to
																						produce discrete-valued draws.
																						Write zeta and xi's index values into zetaindexsimMat, xiindexsimMat
																						Next 10 lines modified by JBJ:  7/11/08, 7/23/08
																						*/

				epsilon = epsiloncdfsimMat[yearInd][personInd];
				zetaInd = GetLocation(&zetaProbMcdf[zetaInd_before][0], epsilon, ZETADIM + 1).Ind1;
				zeta = zetaA[zetaInd];  /* actual value of zeta */
				xi = xicdfsimMat[yearInd][personInd];
				xiInd = GetLocation(&xiProbAcdf[0], xi, XIDIM + 1).Ind1;
				xi = xiA[xiInd];  /* actual value of xi */
				zetaindexsimMat[yearInd][personInd] = zetaInd;
				zetasimMat[yearInd][personInd] = zeta;
				xiindexsimMat[yearInd][personInd] = xiInd;
				xisimMat[yearInd][personInd] = xi;


				/* need to interpolate  over PI to get health cost intercept and variance.
				Using renamed health costs*/
				//Note: We normally interpolate linearly on sigma not var, here we construct the dead household's variance, square root it and weight on these sigmas
				healthCost = MODELPERIOD * exp((hcSIntercept[sex][laghsInd][hsInd][tInd][PIInd1] * weight
					+ hcSIntercept[sex][laghsInd][hsInd][tInd][PIInd2] * (1 - weight)) + deathcosts
					+ (sqrt(pow(hcSSigma[sex][laghsInd][hsInd][tInd][PIInd1], 2.0) + deathVar1) * weight
						+ sqrt(pow(hcSSigma[sex][laghsInd][hsInd][tInd][PIInd2], 2.0) + deathVar2) * (1 - weight)) * (zeta + xi));

				/* Calculate net after tax income for realized interest rate shock */
				/* Need to interpolate over PI to get before tax income  */
				// *?#?* subtracted healthcost from assets RM 08/17 
				grossIncome = rorsim[yearInd] * (cohsimMat[yearInd - 1][personInd]
					- consumptionsimMat[yearInd - 1][personInd])
					+ ySM[sex][PIInd1][tInd] * weight + ySM[sex][PIInd2][tInd] * (1 - weight); //*?#?* replaced savings 05/18
				netIncome = MODELPERIOD * AfterTaxIncomeS(grossIncome);
				// *?#?* Differential tax treatment of singles and couples RM 01/2017

				assets = cohsimMat[yearInd - 1][personInd] - consumptionsimMat[yearInd - 1][personInd];  // This line and next modified by JBJ 4/18
				coh_pre_transfer = assets + netIncome - healthCost;  // Note for people near the transfer line we impose that bequests can't take them below

				DisA = min(assets, AssetDisregardS);
				DisI = min(grossIncome, IncDisregardS); //collect the correct disregards RM 01/19 *?#?*
				coh = max(coh_pre_transfer - (DisA + DisI), cMinS) + DisA + DisI; //We do this twice because of the way we construct the Bequest function on

																				  /*Next 27 lines added by RM to incorporate new bequest timing *?#?*  RM 08/17 */
				if (justdead == 1)
				{
					//Recall the tind dimension is misleading in couples bequests
					if (sex == 0)
					{
						//Single man
						beqwidow = Interpolation(&bequestFunWM[tInd - 1][PIInd1][hsInd][zetaInd][0],
							cashC, coh, CASHDIM) * weight + Interpolation(&bequestFunWM[tInd - 1][PIInd2][hsInd][zetaInd][0],
								cashC, coh, CASHDIM) * (1 - weight);
					}
					else
					{
						//Single woman #RM *?#?* fixed 22/07/2020 to avoid out of array limit
						beqwidow = Interpolation(&bequestFunHM[tInd +WIFEAGEDIF- 1][PIInd1][hsInd][zetaInd][0],
							cashS, coh, CASHDIM) * weight + Interpolation(&bequestFunHM[tInd - 1][PIInd2][hsInd][zetaInd][0],
								cashS, coh, CASHDIM) * (1 - weight);
					} //On gender
					  //Store the bequest  
					beqsimMat[yearInd][personInd] = beqwidow;
					//revert back to skipping
					justdead = 0;
				}
				else
				{
					//*?#?* Added by RM 08/17 - Reset
					beqwidow = 0.0;
					deathcosts = 0.0;
					deathVar1 = 0.0;
					deathVar2 = 0.0;
				}
				// Subtract side bequests
				coh_pre_transfer = coh_pre_transfer - beqwidow;

				// Next 33 lines modified by JBJ 4/18

				Medicaid = 0.0;
				// *?#?* updated due to new timing convention - replacing healthcost and assets in loop RM 08/17 Fixed 11/17 Adjusted for disregard RM 01/19 *?#?*
				if (healthCost > assets + netIncome - DisA - DisI)     // Code in Medicaid -this check is if h}ealthCost>coh_t-1-con_t-1 
				{
					Medicaid = healthCost - (assets + netIncome - DisA - DisI);  //Calculate gap /*changed RM 08/18*/ Adjusted for disregard RM 01/19 *?#?*
				}


				//*?#?* Reorderd RM 22/05/18 UPdated in line with new wequations 31/05/18


				coh = max(coh_pre_transfer - (DisA + DisI), cMinS) + DisA + DisI; // Should be superfluous

				transfersim = max((coh - DisA - DisI) - (coh_pre_transfer - DisA - DisI), 0.0); //Make sure the  transfer doesn't count the disregard
				Medicaid = min(Medicaid, transfersim);
				healthCost = healthCost - Medicaid;
				healthcostsimMat[yearInd][personInd] = healthCost;
				transfersimMat[yearInd][personInd] = transfersim;
				MedicaidsimMat[yearInd][personInd] = Medicaid;
				netIncomesimMat[yearInd][personInd] = netIncome;
				assetsimMat[yearInd][personInd] = assets; //Side bequest not deducted
				cohsimMat[yearInd][personInd] = coh;

				// To get consumption function, interpolate over PI and COH 

				consumption = Interpolation(&consumFunSM[sex][tInd][PIInd1][hsInd][zetaInd][0],
					cashS, coh, CASHDIM) * weight
					+ Interpolation(&consumFunSM[sex][tInd][PIInd2][hsInd][zetaInd][0],
						cashS, coh, CASHDIM) * (1 - weight);
				consumptionsimMat[yearInd][personInd] = consumption;

				// *?#?* Added by RM 08/17 - Reset for all future loops;
				deathcosts = 0.0;
				deathVar1 = 0.0;
				deathVar2 = 0.0;
				justdead = 0;

			}/* end else */

			marstatsim2Mat[yearInd][personInd] = marstatsimMat[yearInd][personInd]; // JBJ:  5/6/09

		} /* on loop through time for singles */


		for (yearInd = yearInd3; yearInd < TDimSims + 1; yearInd++)  /*calendar year-note skipped if never dies*/
		{          //Major changes to incorporate death costs 08/17 RM *?#?*
				   //cHANGES DUE TO HEALTH STATUS AND DEATHCOSTS MATRIX 09/17 RM #?*?#
			if (justdead == 1)
			{
				//New RM *?#?* 06/2018. through to lines: 5431
				assets = cohsimMat[yearInd - 1][personInd] - consumptionsimMat[yearInd - 1][personInd];
				//Pick up the correct income measure
				if (marstatsimMat[yearInd - 1][personInd] < 3) { //Died a single
					grossIncome = ySM[sex][PIInd1][tInd] * weight + ySM[sex][PIInd2][tInd] * (1 - weight);
					//add returns on assets:	
					grossIncome = rorsim[yearInd] * assets + INCDEAD * grossIncome;
					//Taxation:
					netIncome = MODELPERIOD * (AfterTaxIncomeS(grossIncome) * TAXINCDEAD + (1 - TAXINCDEAD) * grossIncome);
				}
				else //A couple
				{
					grossIncome = yCM[PIInd1][tInd] * weight + yCM[PIInd2][tInd] * (1 - weight);
					//add returns on assets:	
					grossIncome = rorsim[yearInd] * assets + INCDEAD * grossIncome;
					//Taxation:
					netIncome = MODELPERIOD * (AfterTaxIncomeC(grossIncome) * TAXINCDEAD + (1 - TAXINCDEAD) * grossIncome);
				}

				coh_pre_transfer = assets + netIncome - deathcosts; //Note: Deathcosts already exponented and allows for for modelperiod
				if (coh_pre_transfer < 0.0) //changed RM 06/18
				{
					//dIFFERENTIATE HEALTHCOST DATA AND MEDICAID ELEMENT 
					healthcostsimMat[yearInd][personInd] = assets + netIncome; // changed RM 06/18
																			   //Residual element picked up by medicaid
					MedicaidsimMat[yearInd][personInd] = deathcosts - (assets + netIncome); /*changed RM 06/18*/
					transfersimMat[yearInd][personInd] = MedicaidsimMat[yearInd][personInd]; /* #?*?# added RM 11/17 */
				}
				else //Store deathcosts!
				{
					healthcostsimMat[yearInd][personInd] = deathcosts; // 11/17 RM *?#?* Added 
				}
				beqsimMat[yearInd][personInd] = max(coh_pre_transfer, 0.0); //Updated RN 31/05/18, new midek equations, *?#?*
			}
			/* household members all dead --> No more logic checks */
			if (justdead == 0) { //Effectively don't overwrite when we have a zeta associated wih deathcosts
				zetaindexsimMat[yearInd][personInd] = -1;   /* JBJ:  7/11/08 */
				zetasimMat[yearInd][personInd] = -1e5; /* JBJ:  7/11/08 */
				xiindexsimMat[yearInd][personInd] = -1;   /* JBJ:  7/23/08 */
				xisimMat[yearInd][personInd] = -1e5; /* JBJ:  7/23/08 */
				healthcostsimMat[yearInd][personInd] = -1.e5; // 08/17 RM *?#?*
				MedicaidsimMat[yearInd][personInd] = -1e5; /* JBJ:  7/23/08 */
				beqsimMat[yearInd][personInd] = -1e5;
			}
			consumptionsimMat[yearInd][personInd] = -1e5;

			cohsimMat[yearInd][personInd] = -1e5;
			assetsimMat[yearInd][personInd] = -1e5;
			netIncomesimMat[yearInd][personInd] = -1e5;
			transfersimMat[yearInd][personInd] = MedicaidsimMat[yearInd][personInd]; /* #?*?# moved RM 4/18 */
			deathcosts = -1e5; // because we will replace healthcosts08/17 RM *?#?*
			deathVar1 = 0.0;
			deathVar2 = 0.0;
			justdead = 0;
			/* Timing for year yearInd:
			marstatsimMat[yearInd]->healthsimhMat[yearInd],
			healthsimwMat[yearInd] or beqsimMat[yearInd-1]-> xisimMat[yearInd-1],
			epsilonsimMat[yearInd-1], zetaindexsimMat[yearInd]-> healthcostsimMat[yearInd]->
			cohsimMat[yearInd]->consumptionsimMat[yearInd] */

			marstatsim2Mat[yearInd][personInd] = marstatsimMat[yearInd][personInd]; // JBJ:  5/6/09




		} /* on loop through time for singles */

		  /* True for all people */
		marstatsim2Mat[0][personInd] = marstatsimMat[0][personInd];        // JBJ:  5/6/09
		marstatsim2Mat[TDimSims][personInd] = marstatsimMat[TDimSims][personInd]; // JBJ:  5/6/09
	}  /* end loop of household */

	   /* commented out RM 09//17 *?#?*  free(tempvec);
	   free(tempV); */
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//  Below is C/GAUSS I/O code written by Ken Housinger                       
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//  This function takes a char* and either reverses bits within bytes or bytes 
//  themselves or both.  It returns a pointer to the original buffer which is  
//  altered. 

unsigned char* gread(unsigned char* inbuf, int bytes, int byte_rev, int bit_rev)
{
	unsigned char* tempbuf;
	unsigned char tempbyte, tempbit;
	int i, j;

	tempbuf = (unsigned char*)malloc(bytes);
	for (i = 0; i < bytes; i++)
	{
		if (byte_rev) *(tempbuf + i) = *(inbuf + bytes - i - 1);
		else *(tempbuf + i) = *(inbuf + i);

		if (bit_rev)
		{
			tempbyte = 0;
			for (j = 0; j < CHAR_BIT; j++)
			{
				tempbit = *(tempbuf + i) >> (CHAR_BIT - j - 1);
				tempbit = tempbit << (CHAR_BIT - 1);
				tempbit = tempbit >> (CHAR_BIT - j - 1);
				tempbyte = tempbyte | tempbit;
			}
			*(tempbuf + i) = tempbyte;
		}
	}

	for (i = 0; i < bytes; i++)
		*(inbuf + i) = *(tempbuf + i);
	free(tempbuf);

	return(inbuf);
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//  This function reads a Gauss v5.0 fmt file into a Matrix structure and  
//  returns the structure.  

GMatrix gau5read(char* fmt)
{
	//  Initialize the matrix to be 1x1 and the byte/bit order to 0.  
	GMatrix mat = { 1, 1 };
	unsigned int i;
	int type, byte, bit;
	unsigned char* cread;
	int bit_rev = 0, byte_rev = 0;
	FILE* fd;

	if (sizeof(int) != 4 || sizeof(double) != 8 || CHAR_BIT != 8)
	{
		printf("Incompatable machine architecture.\n");
		fflush(stdout);
		return (mat);
	}

	//  Allocate enough space to store the header.  
	cread = (unsigned char*)malloc(BASIC_HEADER_LEN);
	//  Open *fmt for reading only.  
	fd = fopen(fmt, "rb");

	//  Read the basic header (128 bytes) all at once.  

	fread((void*)cread, 1, BASIC_HEADER_LEN, fd);
	byte = (int)*(cread + (BYTE_POS * sizeof(int)));  // (0=Backward) 
	bit = (int)*(cread + (BIT_POS * sizeof(int)));    // (0=Backward) 

													   //  To get some system independence, we detect whether we have to reverse 
													   //  the bytes or bits or both.  If x and x_SYSTEM match, no reverse is  
													   //  necessary. 

	if ((bit || BIT_SYSTEM) && !(bit && BIT_SYSTEM)) bit_rev = 1;
	if ((byte || BYTE_SYSTEM) && !(byte && BYTE_SYSTEM)) byte_rev = 1;

	type = *((int*)gread((cread + (TYPE_POS * sizeof(int))), sizeof(int),
		byte_rev, bit_rev));

	//  If the fmt file type is not a scalar, there are another two 
	//  ints of header giving the values of m and n.  If a matrix, also reset n. 

	if (type > SCALAR)
	{
		fread((void*)cread, 1, sizeof(int), fd);
		mat.m = *((unsigned int*)gread(cread, sizeof(int), byte_rev, bit_rev));
		fread((void*)cread, 1, sizeof(int), fd);
		if (type == MATRIX)
			mat.n = *((unsigned int*)gread(cread, sizeof(int), byte_rev, bit_rev));
	}

	//  Allocate memory for the matrix.  The amount needed is m * n * sizeof(double). 
	//  Next, read in the data all at once.  Then use gread to reverse 
	//  bytes/bits if necessary. 

	free(cread);

	mat.data = (double*)malloc(mat.m * mat.n * sizeof(double));
	fread((void*)mat.data, sizeof(double), mat.m * mat.n, fd);
	if (byte_rev || bit_rev)
		for (i = 0; i < mat.m * mat.n; i++)
			gread((unsigned char*)mat.data + (i * sizeof(double)), sizeof(double),
				byte_rev, bit_rev);

	fclose(fd);


	return (mat);
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//  This function writes a Gauss v5.0 fmt file from a Matrix structure. 

void gau5write(char* fmt, GMatrix mat)
{
	//  This ugly mess is the basic header. 

	unsigned int header[(BASIC_HEADER_LEN / sizeof(int)) + 2] =
	{ 0xffffffff, 0, 0xffffffff, 0, 0xffffffff, 0, 0,
		0xabcdef01,1, 0, 1, 1008, sizeof(double), 0, 1,
		SCALAR, 1, 0, BASIC_HEADER_LEN };

	FILE* fd;

	if (sizeof(int) != 4 || sizeof(double) != 8 || CHAR_BIT != 8)
	{
		printf("Incompatable machine architecture.\n");
		fflush(stdout);
		return;
	}

	//  If forward byte, make 6th int 0xffffffff. 
	//  If forward bit, make 7th int 0xffffffff. 

	if (BYTE_SYSTEM) header[BYTE_POS] = 0xffffffff;
	if (BIT_SYSTEM) header[BIT_POS] = 0xffffffff;

	//  If not a scalar, increase the 16th int by 1 and the 19th int (header  
	//  length) by 8 (2 * sizeof(int)).  Also, set m in int 33. 

	if (!(mat.m * mat.n == 1))
	{
		header[TYPE_POS] += 1;
		header[HEADER_LEN_POS] += (2 * sizeof(int));
		header[M_POS] = mat.m;

		//  If not a vector (and not a scalar), increase the 16th int by 1 again 
		//  and set m in int 34. 
		if (!(mat.n == 1))
		{
			header[TYPE_POS] += 1;
			header[N_POS] = mat.n;
		}
	}
	/*
	**Open fmt for writing and create if it does not exist.  If you create it,
	**make it a regular file with permissions 0640.  See comment in gau5read
	**for detail on how read (and similarly, write) work.
	**
	**Order: Write the basic header
	**       If not a scalar, write the other 2 ints of header
	**       Write the m * n elements of data
	*/

	fd = fopen(fmt, "wb");
	if ((mat.m * mat.n == 1))
		fwrite((void*)header, 1, BASIC_HEADER_LEN, fd);
	else
		fwrite((void*)header, 1, BASIC_HEADER_LEN + (2 * sizeof(int)), fd);
	fwrite((void*)mat.data, sizeof(double), mat.m * mat.n, fd);
	fclose(fd);
}

//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//--------------------    Test Section  -----------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//*?#?*  Prints additional output to provide tests
//Created RM 06/2017 based on ptint output code above
#if(TESTCHECKS==1) //Conditional compile on testchecks
void Testprint(void)
{
	int printInd1, printInd2, printInd3, tInd, i, IInd, zetaInd, cashInd, hsInd, hsHInd, hsWInd;
	FILE* printptr; // point to file containing parameters 
	char fullpath[ADDRESS_LEN];

	printptr = fopen(strcat(strcpy(fullpath, outputdir), "UMatS.txt"), "w");  // Printing 

	for (printInd1 = 0; printInd1 < HSDIM; printInd1++)
	{
		for (printInd2 = 0; printInd2 < CONSUMDIM; printInd2++)
		{
			// write value function and policy function to files 
			fprintf(printptr, "%12.4f  ", utilitySM[printInd1][printInd2]);
		} // end loop through cash on hand  
		fprintf(printptr, "\n");

	} // end loop through persistent health shock 

	  // End writing to files 
	fclose(printptr);


	/*
	printptr = fopen(strcat(strcpy(fullpath, outputdir), "BeqUSM.txt"), "w");  // Printing

	for (printInd1 = 0; printInd1<CASHDIM; printInd1++)
	{
	for (printInd2 = 0; printInd2<CONSUMDIM; printInd2++)
	{
	// write value function and policy function to files
	fprintf(printptr, "%12.4f  ", bequestUSM[printInd1][printInd2]);
	} // end loop through cash on hand
	fprintf(printptr, "\n");

	} // end loop through persistent health shock

	// End writing to files
	fclose(printptr);
	*/



	if (switchCouple == 1)
	{

		printptr = fopen(strcat(strcpy(fullpath, outputdir), "UMatC.txt"), "w");  // Printing 

		for (printInd1 = 0; printInd1 < HSDIM; printInd1++)
		{
			for (printInd2 = 0; printInd1 < HSDIM; printInd1++)
			{
				for (printInd3 = 0; printInd3 < CONSUMDIM; printInd3++)
				{
					// write value function and policy function to files 
					fprintf(printptr, "%12.4f  ", utilityCM[printInd1][printInd2][printInd3]);

				} // end loop through cash on hand  
				fprintf(printptr, "\n");

			} // end loop through persistent health shock 
			fprintf(printptr, "\n");
		}
		// End writing to files 
		fclose(printptr);



		printptr = fopen(strcat(strcpy(fullpath, outputdir), "BeqUHWM.txt"), "w");  // Printing 

		for (printInd1 = 0; printInd1 < CASHDIM; printInd1++)
		{
			for (printInd2 = 0; printInd1 < CONSUMDIM; printInd1++)
			{
				for (printInd3 = 0; printInd3 < BEQUESTDIM; printInd3++)
				{
					// write value function and policy function to files 
					//         fprintf(printptr, "%12.4f  ", bequestUHWM[printInd1][printInd2][printInd3]);
				} // end loop through cash on hand  
				fprintf(printptr, "\n");

			} // end loop through persistent health shock 
			fprintf(printptr, "\n");
		}
		// End writing to files 
		fclose(printptr);

		/*  printptr = fopen(strcat(strcpy(fullpath, outputdir), "BeqUCM.txt"), "w");  // Printing

		for (printInd1 = 0; printInd1<CASHDIM; printInd1++)
		{
		for (printInd2 = 0; printInd2<CONSUMDIM; printInd2++)
		{
		// write value function and policy function to files CURRENTLY NOT UPDATED TO PRINT FULLY
		fprintf(printptr, "%12.4f  ", bequestUCM[printInd1][printInd2]);
		} // end loop through cash on hand
		fprintf(printptr, "\n");

		} // end loop through persistent health shock

		// End writing to files
		fclose(printptr);
		} */



		printptr = fopen(strcat(strcpy(fullpath, outputdir), "BeqUCM.txt"), "w");  // Printing 


		for (IInd = 0; IInd < IDIM; IInd++)
		{
			for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
			{
				for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
				{
					for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
					{
						for (cashInd = 0; cashInd < CASHDIM; cashInd++)
						{
							// write value function and policy function to files 
							for (printInd2 = 0; printInd1 < CONSUMDIM; printInd1++)
							{
								fprintf(printptr, "%12.4f  ", bequestUCM[cashInd][IInd][hsHInd][hsWInd][zetaInd][printInd1]);
							}//Removed tiind beqUCM 01/18 RM *?#?*
						} // end loop through cash on hand  
						fprintf(printptr, "\n");

					} // end loop through persistent health shock 
					fprintf(printptr, "\n");

				}// end loop through health status for wife  
			}// end loop through health status for husband 
		}   // end loop through permanent income    

			// End writing to files 
		fclose(printptr);

		printptr = fopen(strcat(strcpy(fullpath, outputdir), "EulerEC.txt"), "w");  // value function 

																					//*?#?* Edited the loop to remove WIFEAGEDIF RM 01/2017
																					// OLD: for (tInd = (TDIMC-WIFEAGEDIF-1); tInd>= 0; tInd--)

		for (tInd = (TDIMC - 1); tInd >= 0; tInd--)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
				{
					for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
					{
						for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
						{
							for (cashInd = 0; cashInd < CASHDIM; cashInd++)
							{
								// write value function and policy function to files 
								fprintf(printptr, "%12.4f  ", EulerErrorSignCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd]);

							} // end loop through cash on hand  
							fprintf(printptr, "\n");

						} // end loop through persistent health shock 
						fprintf(printptr, "\n");

					}// end loop through health status for wife  
				}// end loop through health status for husband 
			}   // end loop through permanent income    
		} // end loop through age 

		  // End writing to files 
		fclose(printptr);

		printptr = fopen(strcat(strcpy(fullpath, outputdir), "EulerAbsEC.txt"), "w");  // value function 


		for (tInd = (TDIMC - 1); tInd >= 0; tInd--)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
				{
					for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
					{
						for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
						{
							for (cashInd = 0; cashInd < CASHDIM; cashInd++)
							{
								// write value function and policy function to files 
								fprintf(printptr, "%12.4f  ", EulerErrorAbsCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd]);

							} // end loop through cash on hand  
							fprintf(printptr, "\n");

						} // end loop through persistent health shock 
						fprintf(printptr, "\n");

					}// end loop through health status for wife  
				}// end loop through health status for husband 
			}   // end loop through permanent income    
		} // end loop through age 

		  // End writing to files 
		fclose(printptr);


	} //if (switchCouple==1)

	  //--------------------------------------------------------------------------------

	printptr = fopen(strcat(strcpy(fullpath, outputdir), "BeqUSM.txt"), "w");  // Printing 

																			   // single case 
	for (i = 0; i < 2; i++)
	{
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (hsInd = 0; hsInd < HSDIM; hsInd++)
				{
					for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
					{
						for (cashInd = 0; cashInd < CASHDIM; cashInd++)
						{
							// write value function and policy function to files 
							for (printInd2 = 0; printInd1 < CONSUMDIM; printInd1++)
							{
								fprintf(printptr, "%12.4f  ", bequestUSM[i][cashInd][IInd][hsInd][zetaInd][printInd1]);
								// *?#?* replaced BequestFunSSM with bequestFunSM as previous identifier not defined RM 01/2017
							}
						}

						fprintf(printptr, "\n");
					}

					fprintf(printptr, "\n");
				}// end loop through health status 
			} // end loop through permanent income    
		} // end loop through sex 
		fclose(printptr);


		printptr = fopen(strcat(strcpy(fullpath, outputdir), "EulerES.txt"), "w");  // value function 

																					// *?#?* Renamed as bequest FS to avoid inconsistency RM 01/2017. OLD:
																					//beqFP    = fopen(strcat(strcpy(fullpath,outputdir),"bequestSF.txt"),"w");  // bequest policy function 

																					// Print value function for t = 1, ..., T  where value function for T+1 is defined as 0 matrix 
																					// single case 
		for (i = 0; i < 2; i++)
		{
			for (tInd = (TDIMS - 1); tInd >= 0; tInd--)
			{
				for (IInd = 0; IInd < IDIM; IInd++)
				{
					for (hsInd = 0; hsInd < HSDIM; hsInd++)
					{
						for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
						{
							for (cashInd = 0; cashInd < CASHDIM; cashInd++)
							{
								// write value function and policy function to files 
								fprintf(printptr, "%12.4f  ", EulerErrorSignSM[i][tInd][IInd][hsInd][zetaInd][cashInd]);
								// *?#?* replaced BequestFunSSM with bequestFunSM as previous identifier not defined RM 01/2017
							}

							fprintf(printptr, "\n");
						}

						fprintf(printptr, "\n");
					}// end loop through health status 
				} // end loop through permanent income    
			} // end loop through age 
		} // end loop through sex 

		  // End writing to files  
		fclose(printptr);

		printptr = fopen(strcat(strcpy(fullpath, outputdir), "EulerAbsES.txt"), "w");  // value function 

																					   // *?#?* Renamed as bequest FS to avoid inconsistency RM 01/2017. OLD:
																					   //beqFP    = fopen(strcat(strcpy(fullpath,outputdir),"bequestSF.txt"),"w");  // bequest policy function 

																					   // Print value function for t = 1, ..., T  where value function for T+1 is defined as 0 matrix 
																					   // single case 
		for (i = 0; i < 2; i++)
		{
			for (tInd = (TDIMS - 1); tInd >= 0; tInd--)
			{
				for (IInd = 0; IInd < IDIM; IInd++)
				{
					for (hsInd = 0; hsInd < HSDIM; hsInd++)
					{
						for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
						{
							for (cashInd = 0; cashInd < CASHDIM; cashInd++)
							{
								// write value function and policy function to files 
								fprintf(printptr, "%12.4f  ", EulerErrorAbsSM[i][tInd][IInd][hsInd][zetaInd][cashInd]);
								// *?#?* replaced BequestFunSSM with bequestFunSM as previous identifier not defined RM 01/2017
							}

							fprintf(printptr, "\n");
						}

						fprintf(printptr, "\n");
					}// end loop through health status 
				} // end loop through permanent income    
			} // end loop through age 
		} // end loop through sex 

		  // End writing to files  
		fclose(printptr);

		printptr = fopen(strcat(strcpy(fullpath, outputdir), "BeqSignEH.txt"), "w");  // value function 

																					  // *?#?* Renamed as bequest FS to avoid inconsistency RM 01/2017. OLD:
																					  //beqFP    = fopen(strcat(strcpy(fullpath,outputdir),"bequestSF.txt"),"w");  // bequest policy function 

																					  // Print value function for t = 1, ..., T  where value function for T+1 is defined as 0 matrix 
																					  // single case 

		for (tInd = (TDIMS - 1); tInd >= 0; tInd--)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (hsInd = 0; hsInd < HSDIM; hsInd++)
				{
					for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
					{
						for (cashInd = 0; cashInd < CASHDIM; cashInd++)
						{
							// write value function and policy function to files 
							fprintf(printptr, "%12.4f  ", BeqErrorSignHM[tInd][IInd][hsInd][zetaInd][cashInd]);
							// *?#?* replaced BequestFunSSM with bequestFunSM as previous identifier not defined RM 01/2017
						}

						fprintf(printptr, "\n");
					}

					fprintf(printptr, "\n");
				}// end loop through health status 
			} // end loop through permanent income    
		} // end loop through age 

		  // End writing to files  
		fclose(printptr);

		printptr = fopen(strcat(strcpy(fullpath, outputdir), "BeqSignEW.txt"), "w");  // value function 

																					  // *?#?* Renamed as bequest FS to avoid inconsistency RM 01/2017. OLD:
																					  //beqFP    = fopen(strcat(strcpy(fullpath,outputdir),"bequestSF.txt"),"w");  // bequest policy function 

																					  // Print value function for t = 1, ..., T  where value function for T+1 is defined as 0 matrix 
																					  // single case 

		for (tInd = (TDIMS - 1); tInd >= 0; tInd--)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (hsInd = 0; hsInd < HSDIM; hsInd++)
				{
					for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
					{
						for (cashInd = 0; cashInd < CASHDIM; cashInd++)
						{
							// write value function and policy function to files 
							fprintf(printptr, "%12.4f  ", BeqErrorSignWM[tInd][IInd][hsInd][zetaInd][cashInd]);
							// *?#?* replaced BequestFunSSM with bequestFunSM as previous identifier not defined RM 01/2017
						}

						fprintf(printptr, "\n");
					}

					fprintf(printptr, "\n");
				}// end loop through health status 
			} // end loop through permanent income    
		} // end loop through age 

		  // End writing to files  
		fclose(printptr);


		printptr = fopen(strcat(strcpy(fullpath, outputdir), "BeqAbsEH.txt"), "w");  // value function 

																					 // *?#?* Renamed as bequest FS to avoid inconsistency RM 01/2017. OLD:
																					 //beqFP    = fopen(strcat(strcpy(fullpath,outputdir),"bequestSF.txt"),"w");  // bequest policy function 

																					 // Print value function for t = 1, ..., T  where value function for T+1 is defined as 0 matrix 
																					 // single case 

		for (tInd = (TDIMS - 1); tInd >= 0; tInd--)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (hsInd = 0; hsInd < HSDIM; hsInd++)
				{
					for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
					{
						for (cashInd = 0; cashInd < CASHDIM; cashInd++)
						{
							// write value function and policy function to files 
							fprintf(printptr, "%12.4f  ", BeqErrorAbsHM[tInd][IInd][hsInd][zetaInd][cashInd]);
							// *?#?* replaced BequestFunSSM with bequestFunSM as previous identifier not defined RM 01/2017
						}

						fprintf(printptr, "\n");
					}

					fprintf(printptr, "\n");
				}// end loop through health status 
			} // end loop through permanent income    
		} // end loop through age 

		  // End writing to files  
		fclose(printptr);

		printptr = fopen(strcat(strcpy(fullpath, outputdir), "BeqAbsEW.txt"), "w");  // value function 

																					 // *?#?* Renamed as bequest FS to avoid inconsistency RM 01/2017. OLD:
																					 //beqFP    = fopen(strcat(strcpy(fullpath,outputdir),"bequestSF.txt"),"w");  // bequest policy function 

																					 // Print value function for t = 1, ..., T  where value function for T+1 is defined as 0 matrix 
																					 // single case 

		for (tInd = (TDIMS - 1); tInd >= 0; tInd--)
		{
			for (IInd = 0; IInd < IDIM; IInd++)
			{
				for (hsInd = 0; hsInd < HSDIM; hsInd++)
				{
					for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
					{
						for (cashInd = 0; cashInd < CASHDIM; cashInd++)
						{
							// write value function and policy function to files 
							fprintf(printptr, "%12.4f  ", BeqErrorAbsWM[tInd][IInd][hsInd][zetaInd][cashInd]);
							// *?#?* replaced BequestFunSSM with bequestFunSM as previous identifier not defined RM 01/2017
						}

						fprintf(printptr, "\n");
					}

					fprintf(printptr, "\n");
				}// end loop through health status 
			} // end loop through permanent income    
		} // end loop through age 

		  // End writing to files  
		fclose(printptr);

	}







	//-----------------------------------------------------------------------
	//------------------------------------------------------------------------------
	/* Computes Euler equation errors
	Singles case. *?#?* Created by RM 06/2017 based on GetRulesSingle
	*/
	void GetErrorsSingle(int iAssetsmin, int iAssetsmax)
	{
		int tInd, cashInd, i, IInd, hsInd, zetaInd;
		double nextper = 0.0;       // used in error calculation to record maximum


		double* tempvec;
		int recsize = IDIM * HSDIM * ZETADIM * CASHDIM;
		tempvec = (double*)calloc(recsize, sizeof(double));

		if ((useMPI < 2) || (rank == (size - 1)))
			printf("Solving for Errors. \n ");
		fflush(stdout);

		// Switched order of loops to make it more intuitive with the parallelization **** 04/2014       
		// COH is now only inside the age loop, over which we cannot parallelize.  
		for (tInd = (TDIMS - 1); tInd >= 0; tInd--) // today's age
		{
			if ((useMPI < 2) || (rank == (size - 1))) printf("Age=%d \n ", tInd * MODELPERIOD + TSTART); // *?#?* Added Model period to print correct ages RM 01/2017
			fflush(stdout);

			for (i = 0; i < 2; i++) // gender
			{
				for (cashInd = iAssetsmin; cashInd < iAssetsmax; cashInd++)   // COH
				{ // *?#?* Reversed coh and gender due to MPI implementation RM 03/2017

					for (IInd = 0; IInd < IDIM; IInd++) // PI
					{
						for (hsInd = 0; hsInd < HSDIM; hsInd++) // today's health
						{
							for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++) // today's persistent medex shock
							{
								// compute expected discounted marginal utility


								// loop through possible consumption choice 

								nextper = GetMarginalSingle(i, tInd, IInd, hsInd, zetaInd, cashInd);
								//Invert it 
								nextper = pow(nextper, 1.0 / (-nu));

								//If switch bequest is 0 the final period Euler calculates incorrectly (because we invert 0)
								//In that case we impose that the RHS is the cash on hand. (note not a problem for couples who live as singles)    
								if ((tInd == TDIMS - 1) && (switchBeq == 0))
								{
									nextper = cashS[cashInd];
								}
								//Take the relative error           
								EulerErrorSignSM[i][tInd][IInd][hsInd][zetaInd][cashInd] = (consumFunSM[i][tInd][IInd][hsInd][zetaInd][cashInd] - nextper) / consumFunSM[i][tInd][IInd][hsInd][zetaInd][cashInd];
								EulerErrorAbsSM[i][tInd][IInd][hsInd][zetaInd][cashInd] = fabs(EulerErrorSignSM[i][tInd][IInd][hsInd][zetaInd][cashInd]);


							}// end loop through persistent health shock        
						}// end loop through health status    
					}// end loop through permanent income    

				} // end loop for cash on hand 
				  // MPI-specific Code:  Merge output from different processors 
				if (useMPI == 2)
				{
					//Begin the automated commenting *?#?*- Added control sequence RM 03/17
#if(MPI_COMMENT==1)
					MPI_Allreduce(EulerErrorSignSM[i][tInd][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
					copyit(EulerErrorSignSM[i][tInd][0][0][0], tempvec, recsize);
					MPI_Allreduce(EulerErrorAbsSM[i][tInd][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
					copyit(EulerErrorAbsSM[i][tInd][0][0][0], tempvec, recsize);
#endif     //(MPI_COMMENT==1)
#if(MPI_COMMENT==2) //conditional compile on using openMP *?#?*- Added control sequence RM 11/17
#pragma omp barrier //wait until every processor has hit this point
#endif  //close on Openmp 
				} //Close if on MPI use
			}  // end loop through gender 

		} // end loop through age 
		free(tempvec);
	}

	//--------------------------------------------------------------------------------
	//--------------------------------------------------------------------------------
	/* Solve for the expected marginal utility of consumption (weighted by distribution of asset returns and discounted by beta)
	tomorrow given the optimal rules and given the state today
	*?#?* Created by RM 06/2017 based on GetValueSingle

	*/


	double GetMarginalSingle(int i, int tInd, int  IInd, int hsInd, int zetaInd,
		int cashInd)
	{
		int  rInd, hsIndN, zetaIndN, xiInd;
		double cashnet, savings, medcostshifter, cashOnHand;
		double marginalU, beqmarg;
		double sum; // sum is the expected value next period    
		double margavgtax; //used to calculate the marginal tax rate
		double avgtax; //used to calculate the avg tax rat
		sum = 0.0;  // initialize

					// Loop through possible next period states 
					// savings does not need to be computed, every single time, in the inner loop. 25/04/2014 MDN ****
					// *?#?*
					// Used consumption grid for couples  cashnet= cashS[cashInd]-consumC[consumInd]; Corrected. 12/12/2016 RM

		savings = cashS[cashInd] - consumFunSM[i][tInd][IInd][hsInd][zetaInd][cashInd];
		//DOn't calculate marginal utility from next period consumption in the last period. (think 0s and INADA)
		if (tInd == TDIMS - 1)
		{
			sum = 0.0;
		}
		else
		{
			for (rInd = 0; rInd < RDIM; rInd++)
			{

				// *?#?* Differential tax treatment of singles and couples RM 01/2017
				// Swapped to AfterTaxIncomeS from AfterTaxIncome
				//Changed to be consistent with new timing convention RM 08/2017
				for (hsIndN = 0; hsIndN < HSDIM; hsIndN++)
				{
					//updated RM 09/17 for lagged healthcosts

					medcostshifter = hcSIntercept[i][hsInd][hsIndN][tInd + 1][IInd];

					for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
					{
						for (xiInd = 0; xiInd < XIDIM; xiInd++)
						{
							//updated RM 09/17 for lagged healthcosts

							cashnet = savings - MODELPERIOD * exp(medcostshifter + hcSSigma[i][hsInd][hsIndN][tInd + 1][IInd] * (zetaA[zetaIndN] + xiA[xiInd]));
							//Marginal taxes must occur before we roll income into cashnet:
							margavgtax = MargChange2AvgTaxIncomeS(rA[rInd] * cashnet + (ySM[i][IInd][tInd + 1]));
							avgtax = AvgTaxRateIncomeS(rA[rInd] * cashnet + (ySM[i][IInd][tInd + 1]));
							cashOnHand = cashnet + MODELPERIOD * AfterTaxIncomeS(rA[rInd] * cashnet + (ySM[i][IInd][tInd + 1])); // savings after medex 




																																 //We loop through in exactly the same way to construct expected marginal utility. With one key change
							if (cashOnHand < cMinS)
							{
								continue;
								//No marginal return to savings in this case (Hubbard et al 1994 indicator is 0)


							}
							else
							{
								//Take today's savings. Interpolate the consumption rule tomorrow.  

								marginalU = (1 + delta[hsIndN]) * pow(Interpolation(&consumFunSM[i][tInd + 1][IInd][hsIndN][zetaIndN][0], cashS, cashOnHand, CASHDIM), -nu);
								//Add this to the Expectation (including the value of transforming consumption between periods r accounting for changes to tax rate)
								sum += hsProbSM[i][tInd][IInd][hsInd][hsIndN] * zetaProbM[zetaInd][zetaIndN] * rProbA[rInd] * xiProbA[xiInd] * marginalU
									* (1 + MODELPERIOD * rA[rInd] * (1 - avgtax) - margavgtax * MODELPERIOD * (rA[rInd] * cashnet + (ySM[i][IInd][tInd + 1])));
								//The total return to saving is standard 1+r (evaluated after the tax on r) plus the marginal change to the avg tax level it induces
							}
						}
					}
				}
			} // end looping through possible next period states 
		}// End if condition on final period
		 //Calculate the marginal bequest utility
		beqmarg = phi0 * pow(cashOnHand + k0, -nu);

		return beta * (1 - survivalProbSM[i][tInd][hsInd][IInd]) * beqmarg
			+ beta * survivalProbSM[i][tInd][hsInd][IInd] * sum;
	}

	//--------------------------------------------------------------------------------
	//--------------------------------------------------------------------------------
	/* Solve Euler Equation Error for t = 1, ..., T.
	Couples case
	*?#?* Created by RM 06/2017 based on GetRulesCouples
	*/
	void GetErrorsCouples(int iAssetsmin, int iAssetsmax)
	{
		int  tInd, cashInd, IInd, hsHInd, hsWInd, zetaInd;
		double nextper = 0.0;     // used in maximization to record maximum
		FILE* file_pointer;
		char fullpath[ADDRESS_LEN];



		double* tempvec, * tempV;
		int recsize = IDIM * HSDIM * HSDIM * ZETADIM * CASHDIM; // *?#?* Fixed size of the Dimension to include IDIM RM 03/2017
		tempvec = (double*)calloc(recsize, sizeof(double));
		tempV = (double*)calloc(recsize, sizeof(double));

		if ((useMPI < 2) || (rank == (size - 1)))
			printf("Solving for Errors COUPLES. \n ");
		fflush(stdout);

		// notice that all loops refer to today's state variables, except for the one for consumption
		for (tInd = (TDIMC - 1); tInd >= 0; tInd--) //  *?#?* WIFEAGEDIF deleted in keeping with new TDIM structure RM 01/2017
		{
			if ((useMPI < 2) || (rank == (size - 1))) printf("Age=%d \n ", tInd * MODELPERIOD + TSTART); // *?#?* Added Model period to print correct ages RM 01/2017
			fflush(stdout);

			GetBeqErrorCouples(tInd, iAssetsmin, iAssetsmax);
#if(MPI_COMMENT==2) //conditional compile on using openMP *?#?*- Added control sequence RM 11/17
#pragma omp barrier //wait until every processor has hit this point
#endif  //close on Openmp 
			for (cashInd = iAssetsmin; cashInd < iAssetsmax; cashInd++)
				// COH for (cashInd = 0; cashInd<CASHDIM; cashInd++) 
			{ // **** 04/2014 Couples did not appear to have been parallelized. Noticed commented out instruction above
				for (IInd = 0; IInd < IDIM; IInd++)
				{
					for (hsHInd = 0; hsHInd < HSDIM; hsHInd++)
					{
						for (hsWInd = 0; hsWInd < HSDIM; hsWInd++)
						{
							for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++)
							{


								nextper = GetMarginalCouples(tInd, IInd, hsHInd, hsWInd, zetaInd, cashInd);
								//Invert it 
								nextper = pow(nextper, 1.0 / (-nu));
								//Equivalise consumption
								nextper = nextper * eta;

								//Take the relative error                               
								EulerErrorSignCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd] = (consumFunCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd] - nextper) / (consumFunCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd]);
								EulerErrorAbsCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd] = fabs(EulerErrorSignCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd]);



							}// end loop through persistent health shock 
						}// end loop through health status for wife                
					}// end loop through health status for husband 
				} // end loop through permanent income    
			}// end loop through cash on hand  
			file_pointer = fopen(strcat(strcpy(fullpath, outputdir), "ErrorCoupBreakDown.txt"), "a");
			fprintf(file_pointer, "\n");
			fclose(file_pointer);

			// MPI-specific Code:  Merge output from different processors 
			if (useMPI == 2)
			{
				//Begin the automated commenting *?#?*- Added control sequence RM 03/17
				// *?#?* Changed to explicit pointers with all dimensions for readability RM 03/2017
#if(MPI_COMMENT==1)
				MPI_Allreduce(&EulerErrorSignCM[tInd][0][0][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
				copyit(&EulerErrorSignCM[tInd][0][0][0][0][0], tempvec, recsize);
				MPI_Allreduce(&EulerErrorAbsCM[tInd][0][0][0][0][0], tempvec, recsize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
				copyit(&EulerErrorAbsCM[tInd][0][0][0][0][0], tempvec, recsize);

#endif     //(MPI_COMMENT==1)
#if(MPI_COMMENT==2) //conditional compile on using openMP *?#?*- Added control sequence RM 11/17
#pragma omp barrier //wait until every processor has hit this point
#endif  //close on Openmp 
			}
		} // end loop through age 

		free(tempvec);
		free(tempV);
	}

	//--------------------------------------------------------------------------------
	//--------------------------------------------------------------------------------
	/* Solve for the expected marginal utility of consumption (weighted by distribution of asset returns and discounted by beta)
	tomorrow given the optimal rules and given the state today

	*?#?* Created by RM 06/2017 based on GetRulesSingle
	*/
	double GetMarginalCouples(int tInd, int IInd, int hsHInd, int hsWInd, int zetaInd,
		int cashInd)
	{
		int rInd, hsHIndN, hsWIndN, zetaIndN, xiInd;

		double cashnet, savings, medcostshifter, cashOnHand, marginalU;

		double sumC = 0.0;          // expected marginal Utility next period in case both couple members survive
		double sumH = 0.0;      // expected marginal Utility next period in case husband dies
		double sumW = 0.0;      // expected marginal Utility next period in case wife dies
		double beqmargC, beqmargH, beqmargW, beqcost; //Bequest marginal utility depending on who dies
													  // There is an optimal bequest amount conditional on 
													  // each consumption level for the couple while both alive.
		double margavgtax, avgtax;
		FILE* file_pointer;
		char fullpath[ADDRESS_LEN];

		file_pointer = fopen(strcat(strcpy(fullpath, outputdir), "ErrorCoupBreakDown.txt"), "a");


		savings = cashC[cashInd] - consumFunCM[tInd][IInd][hsHInd][hsWInd][zetaInd][cashInd]; // coh - consumption

		beqmargC = 0.0;
		beqmargH = 0.0;
		beqmargW = 0.0;
		//DOn't calculate marginal utility from next period consumption in the last period. (think 0s and INADA)
		if (tInd == TDIMC - 1)
		{
			sumC = 0.0;
			sumH = 0.0;
			sumW = 0.0;
			//Husband dies first, wife may live as a single
			for (rInd = 0; rInd < RDIM; rInd++) // interest rate realization next period
			{

				// *?#?* Differential tax treatment of singles and couples RM 01/2017
				//Switched AfterTaxIncome to AfterTaxIncomeS because single household after spouse dies

				// loop through other possible next period states other than interest rate


				for (hsWIndN = 0; hsWIndN < HSDIM; hsWIndN++) // wife's health status
				{
					// *?#?*
					// the mecostshifter DOES need to be in the inner loop. In 2014 version multiplying whole medcostshifter
					// by zeta value --> shifting the mean medical expenditure as well as the variance. Should be using variance
					// to scale zeta. 12/12/2016 RM

					//Added death costs and changed timing 08/17 RM
					//Added lagged health 09/17 RM
					//updated RM 09/17 for lagged healthcosts

					medcostshifter = hcSIntercept[1][hsWInd][hsWIndN][tInd + 1 - WIFEAGEDIF][IInd] + +laghealthIntercept[0][hsHInd] + deathcostsIntercept[0][IInd];

					for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
					{
						for (xiInd = 0; xiInd < XIDIM; xiInd++)
						{
							//We loop through in exactly the same way to construct expected marginal utility. With one key change
							//updated RM 09/17 for lagged healthcosts

							cashnet = savings - MODELPERIOD * exp(medcostshifter + (sqrt(pow(hcSSigma[1][hsWInd][hsWIndN][tInd + 1 - WIFEAGEDIF][IInd], 2.0) + laghealthVar[0][hsHInd] + deathcostsVar[0][IInd])) * (zetaA[zetaIndN] + xiA[xiInd]));
							//Marginal taxes must occur before we roll income into cashnet:

							margavgtax = MargChange2AvgTaxIncomeS(rA[rInd] * cashnet + (ySM[1][IInd][tInd + 1 - WIFEAGEDIF]));
							avgtax = AvgTaxRateIncomeS(rA[rInd] * cashnet + (ySM[1][IInd][tInd + 1 - WIFEAGEDIF]));

							cashOnHand = cashnet + MODELPERIOD * AfterTaxIncomeS(rA[rInd] * cashnet + (ySM[1][IInd][tInd + 1 - WIFEAGEDIF]));



							if (cashOnHand < cMinS)
							{
								continue;
								//No marginal return to savings in this case (Hubbard et al 1994 indicator is 0)
							}
							else
							{
								//Take today's savings. Interpolate the consumption rule tomorrow.
								beqcost = Interpolation(&bequestFunHM[tInd][IInd][hsWIndN][zetaIndN][0], cashS, cashOnHand, CASHDIM);

								cashOnHand = cashOnHand - beqcost;

								marginalU = (1 + delta[hsWIndN]) * pow(Interpolation(&consumFunSM[1][tInd + 1 - WIFEAGEDIF][IInd][hsWIndN][zetaIndN][0], cashS, cashOnHand, CASHDIM), -nu);

								beqmargH = phi1 * pow(beqcost + k1, -nu); //Marginal bequest utility when Husband dies
																		  //Add this to the Expectation (including the value of transforming consumption between periods r accounting for changes to tax rate)
								sumH += hsProbSM[1][tInd][IInd][hsWInd][hsWIndN] * zetaProbM[zetaInd][zetaIndN] * rProbA[rInd] * xiProbA[xiInd] * (marginalU
									* (1 + MODELPERIOD * rA[rInd] * (1 - avgtax) - margavgtax * MODELPERIOD * (rA[rInd] * cashnet + (ySM[1][IInd][tInd + 1 - WIFEAGEDIF]))) + beqmargH);
								//The total return to saving is standard 1+r (evaluated after the tax on r) plus the marginal change to the avg tax level it induces
							}

						}  // for (xiInd = 0; xiInd<XIDIM; xiInd++)
					} // for (zetaIndN = 0; zetaIndN<ZETADIM; zetaIndN++)
				} // for (hsHIndN = 0; hsHIndN<HSDIM; hsHIndN++)
			}// for (rInd = 0; rInd<RDIM; rInd++)
		}// on if
		else
		{
			//Husband dies first, wife may live as a single

			for (rInd = 0; rInd < RDIM; rInd++) // interest rate realization next period
			{

				// *?#?* Differential tax treatment of singles and couples RM 01/2017
				//Switched AfterTaxIncome to AfterTaxIncomeS because single household after spouse dies

				// loop through other possible next period states other than interest rate


				for (hsWIndN = 0; hsWIndN < HSDIM; hsWIndN++) // wife's health status
				{
					// *?#?*
					// the mecostshifter DOES need to be in the inner loop. In 2014 version multiplying whole medcostshifter
					// by zeta value --> shifting the mean medical expenditure as well as the variance. Should be using variance
					// to scale zeta. 12/12/2016 RM

					//Added death costs and changed timing 08/17 RM

					medcostshifter = hcSIntercept[1][hsWInd][hsWIndN][tInd - WIFEAGEDIF + 1][IInd] + laghealthIntercept[0][hsHInd] + deathcostsIntercept[0][IInd];
					for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
					{
						for (xiInd = 0; xiInd < XIDIM; xiInd++)
						{
							//We loop through in exactly the same way to construct expected marginal utility. With one key change
							cashnet = savings - MODELPERIOD * exp(medcostshifter + (sqrt(pow(hcSSigma[1][hsWInd][hsWIndN][tInd + 1 - WIFEAGEDIF][IInd], 2.0) + laghealthVar[0][hsHInd] + deathcostsVar[0][IInd])) * (zetaA[zetaIndN] + xiA[xiInd]));

							//Marginal taxes must occur before we roll income into cashnet:

							margavgtax = MargChange2AvgTaxIncomeS(rA[rInd] * cashnet + (ySM[1][IInd][tInd + 1 - WIFEAGEDIF]));
							avgtax = AvgTaxRateIncomeS(rA[rInd] * cashnet + (ySM[1][IInd][tInd + 1 - WIFEAGEDIF]));

							cashOnHand = cashnet + MODELPERIOD * AfterTaxIncomeS(rA[rInd] * cashnet + (ySM[1][IInd][tInd + 1 - WIFEAGEDIF]));

							if (cashOnHand < cMinS)
							{
								sumH += 0.0; //or continue;
											 //No marginal return to savings in this case (Hubbard et al 1994 indicator is 0)
							}
							else
							{
								//Take today's savings. Interpolate the consumption rule tomorrow.
								beqcost = Interpolation(&bequestFunHM[tInd][IInd][hsWIndN][zetaIndN][0], cashS, cashOnHand, CASHDIM);

								cashOnHand = cashOnHand - beqcost;

								marginalU = (1 + delta[hsWIndN]) * pow(Interpolation(&consumFunSM[1][tInd + 1 - WIFEAGEDIF][IInd][hsWIndN][zetaIndN][0], cashS, cashOnHand, CASHDIM), -nu);

								beqmargH = phi1 * pow(beqcost + k1, -nu); //Marginal bequest utility when Husband dies
																		  //Add this to the Expectation (including the value of transforming consumption between periods r accounting for changes to tax rate)
								sumH += hsProbSM[1][tInd][IInd][hsWInd][hsWIndN] * zetaProbM[zetaInd][zetaIndN] * rProbA[rInd] * xiProbA[xiInd] * (marginalU
									* (1 + MODELPERIOD * rA[rInd] * (1 - avgtax) - margavgtax * MODELPERIOD * (rA[rInd] * cashnet + (ySM[1][IInd][tInd + 1 - WIFEAGEDIF]))) * omega + beqmargH); //  *?#?* added omega RM 10/17
																																															//The total return to saving is standard 1+r (evaluated after the tax on r) plus the marginal change to the avg tax level it induces
							}

						}  // for (xiInd = 0; xiInd<XIDIM; xiInd++)
					} // for (zetaIndN = 0; zetaIndN<ZETADIM; zetaIndN++)
				} // for (hsHIndN = 0; hsHIndN<HSDIM; hsHIndN++)
			}// for (rInd = 0; rInd<RDIM; rInd++)

			 // Notice that bequestUHWM is constrained as COH TODAY-consumption today, as should be. 
			 // WIFE DIES FIRST f
			for (rInd = 0; rInd < RDIM; rInd++) // interest rate realization next period
			{
				// *?#?* Differential tax treatment of singles and couples RM 01/2017
				//Switched AfterTaxIncome to AfterTaxIncomeS because single household after spouse dies


				for (hsHIndN = 0; hsHIndN < HSDIM; hsHIndN++)
				{
					// *?#?* 
					// Same change as in husband dies first  12/12/2016 RM
					//08/17 added deathcosts and new timing
					//updated RM 09/17 for lagged healthcosts

					medcostshifter = hcSIntercept[0][hsHInd][hsHIndN][tInd + 1][IInd] + laghealthIntercept[1][hsWInd] + deathcostsIntercept[1][IInd];

					// 2014 version:
					//medcostshifter=hcSIntercept[0][hsHIndN][tInd+1][IInd]+hcSSigma[0][hsHIndN][tInd+1][IInd];
					for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
					{
						for (xiInd = 0; xiInd < XIDIM; xiInd++)
						{
							//We loop through in exactly the same way to construct expected marginal utility. With one key change
							//updated RM 09/17 for lagged healthcosts
							cashnet = savings - MODELPERIOD * exp(medcostshifter + (sqrt(pow(hcSSigma[0][hsHInd][hsHIndN][tInd + 1][IInd], 2.0) + laghealthVar[1][hsWInd] + deathcostsVar[1][IInd])) * (zetaA[zetaIndN] + xiA[xiInd]));
							//Marginal taxes must occur before we roll income into cashnet:

							margavgtax = MargChange2AvgTaxIncomeS(rA[rInd] * cashnet + (ySM[0][IInd][tInd + 1]));
							avgtax = AvgTaxRateIncomeS(rA[rInd] * cashnet + (ySM[0][IInd][tInd + 1]));


							cashOnHand = cashnet + MODELPERIOD * AfterTaxIncomeS(rA[rInd] * cashnet + (ySM[0][IInd][tInd + 1])); // savings before medex and gvt transfers
																																 // loop through other next period states, besides interest rate




							if (cashOnHand < cMinS)
							{
								sumW += 0.0; //or continue;
											 //No marginal return to savings in this case (Hubbard et al 1994 indicator is 0)
							}
							else
							{
								//Take today's savings. Interpolate the consumption rule tomorrow.

								beqcost = Interpolation(&bequestFunWM[tInd][IInd][hsHIndN][zetaIndN][0], cashS, cashOnHand, CASHDIM);

								cashOnHand = cashOnHand - beqcost;
								marginalU = (1 + delta[hsHIndN]) * pow(Interpolation(&consumFunSM[0][tInd + 1][IInd][hsHIndN][zetaIndN][0], cashS, cashOnHand, CASHDIM), -nu);

								beqmargW = phi1 * pow(beqcost + k1, -nu); //Marginal bequest utility when wife dies
																		  //Add this to the Expectation (including the value of transforming consumption between periods r accounting for changes to tax rate)
								sumW += hsProbSM[0][tInd][IInd][hsHInd][hsHIndN] * zetaProbM[zetaInd][zetaIndN] * rProbA[rInd] * xiProbA[xiInd] * (marginalU
									* (1 + MODELPERIOD * rA[rInd] * (1 - avgtax) - margavgtax * MODELPERIOD * (rA[rInd] * cashnet + (ySM[0][IInd][tInd + 1]))) * omega + beqmargW); //  *?#?* added omega RM 10/17
																																											   //The total return to saving is standard 1+r (evaluated after the tax on r) plus the marginal change to the avg tax level it induces
							}

						}  // for (xiInd = 0; xiInd<XIDIM; xiInd++)
					} // for (zetaIndN = 0; zetaIndN<ZETADIM; zetaIndN++)
				} // for (hsHIndN = 0; hsHIndN<HSDIM; hsHIndN++)
			}// for (rInd = 0; rInd<RDIM; rInd++)

			 // BOTH ALIVE NEXT PERIOD
			for (rInd = 0; rInd < RDIM; rInd++) // interest rate realization next period
			{
				// *?#?* Differential tax treatment of singles and couples RM 01/2017
				//Switched AfterTaxIncome to AfterTaxIncomeC because couple with both spouses alive

				for (hsHIndN = 0; hsHIndN < HSDIM; hsHIndN++)
				{
					for (hsWIndN = 0; hsWIndN < HSDIM; hsWIndN++)
					{    // *?#?* 
						 // Same change as in husband dies first  12/12/2016 RM
						 //updated RM 09/17 for lagged healthcosts

						medcostshifter = hcCIntercept[hsHInd][hsHIndN][hsWInd][hsWIndN][tInd + 1][IInd];

						// 2014 version: 

						// medcostshifter=hcCIntercept[hsHIndN][hsWIndN][tInd+1][IInd]+hcCSigma[hsHIndN][hsWIndN][tInd+1][IInd];       
						for (zetaIndN = 0; zetaIndN < ZETADIM; zetaIndN++)
						{
							for (xiInd = 0; xiInd < XIDIM; xiInd++)
							{
								//We loop through in exactly the same way to construct expected marginal utility. With one key change
								//updated RM 09/17 for lagged healthcosts

								cashnet = savings - MODELPERIOD * exp(medcostshifter + hcCSigma[hsHInd][hsHIndN][hsWInd][hsWIndN][tInd + 1][IInd] * (zetaA[zetaIndN] + xiA[xiInd]));
								//Marginal taxes must occur before we roll income into cashnet:

								margavgtax = MargChange2AvgTaxIncomeC(rA[rInd] * cashnet + (yCM[IInd][tInd + 1]));
								avgtax = AvgTaxRateIncomeC(rA[rInd] * cashnet + (yCM[IInd][tInd + 1]));


								cashOnHand = cashnet + MODELPERIOD * AfterTaxIncomeC(rA[rInd] * cashnet + (yCM[IInd][tInd + 1])); // savings before medex and gvt transfers
																																  // bequestFunHM is the optimal choice of bequest giving consumption choice    
																																  // loop through other possible next period states 



								if (cashOnHand < cMinC)
								{
									sumC += 0.0; //or continue;
												 //No marginal return to savings in this case (Hubbard et al 1994 indicator is 0)
								}
								else
								{
									//Create marginal utility and sum with stochastic return
									//Take today's savings. Interpolate the consumption rule tomorrow.  


									marginalU = (1 + delta[hsHIndN] + 1 + delta[hsWIndN]) * pow((Interpolation(&consumFunCM[tInd + 1][IInd][hsHIndN][hsWIndN][zetaIndN][0],
										cashC, cashOnHand, CASHDIM)) / eta, -nu);
									//Add this to the Expectation (including the value of transforming consumption between periods r accounting for changes to tax rate)

									sumC += hsProbCM[0][tInd][IInd][hsHInd][hsHIndN] * hsProbCM[1][tInd][IInd][hsWInd][hsWIndN]
										* zetaProbM[zetaInd][zetaIndN] * rProbA[rInd] * xiProbA[xiInd]
										* marginalU * (1 + MODELPERIOD * rA[rInd] * (1 - avgtax) - margavgtax * MODELPERIOD * (rA[rInd] * cashnet + (yCM[IInd][tInd + 1])));



									//The total return to saving is standard 1+r (evaluated after the tax on r) plus the marginal change to the avg tax level it induces
								}



							}
						}
					}
				}
			}// end looping through possible next period's interest rate

		} //End if on final skip

		  //generate marginal bequest utility
		beqmargC = phi2 * pow(savings + k2, -nu); //Marginal bequest utility for couples

		fprintf(file_pointer, "tInd: %5d, IInd: %5d, hsHInd: %5d, hsWInd: %5d,zetaInd: %5d cashind: %5d, beqmargC: %12.20f,  beqmargH: %12.20f, beqmargW: %12.20f, SumC: %12.20f, SumH: %12.20f, SumW: %12.20f ", tInd, IInd, hsHInd, hsWInd, zetaInd, cashInd,
			beqmargC, beqmargH, beqmargW, sumC, sumH, sumW);
		fprintf(file_pointer, "\n");
		fclose(file_pointer);

		//create the final expected marginal utility
		return beta * (
			(1 - survivalProbCM[0][tInd][hsHInd][IInd]) * (1 - survivalProbCM[1][tInd][hsWInd][IInd]) * beqmargC
			+ survivalProbCM[0][tInd][hsHInd][IInd] * survivalProbCM[1][tInd][hsWInd][IInd] * sumC
			+ (1 - survivalProbCM[0][tInd][hsHInd][IInd]) * survivalProbCM[1][tInd][hsWInd][IInd] * sumH
			+ survivalProbCM[0][tInd][hsHInd][IInd] * (1 - survivalProbCM[1][tInd][hsWInd][IInd]) * sumW);  // *?#?* Removed omega 10/17

	}
	/*--------------------------------------------------------------------------------*/
	/*--------------------------------------------------------------------------------*/

	void GetBeqErrorCouples(int tInd, int iAssetsmin, int iAssetsmax)
	{
		int  cashInd, hsInd, zetaInd, IInd;

		double  cashOnHand;
		double sumH, sumW;
		double marginalU;
		double* tempvec2;
		int recsize2 = IDIM * HSDIM * ZETADIM * CASHDIM;
		tempvec2 = (double*)calloc(recsize2, sizeof(double));


		sumH = 0.0;  // initialize
		sumW = 0.0;  // initialize

					 /* *?#?* for each possibility (dead husband, dead wife)- we compute the optimal bequest.
					 These bequests occur as an immediate give away (i.e. death and death associated medical expenses are realised first)
					 so households cannot give all away to their children, file for bankruptcy and claim medicaid

					 we define these rules on the beggining of next period cash

					 Solving this way is effectively 2 stage budgeting*/

					 //NOTE THIS GIVES A LOT OF NEGATIVE NUMBERS BEFORE BEQUESTS KICK IN
					 //Use the optimal value
					 //HUSBAND DIES FIRST

		for (cashInd = iAssetsmin; cashInd < iAssetsmax; cashInd++)   // COH
		{

			for (IInd = 0; IInd < IDIM; IInd++) // PI
			{
				for (hsInd = 0; hsInd < HSDIM; hsInd++) // today's health
				{
					for (zetaInd = 0; zetaInd < ZETADIM; zetaInd++) // today's persistent medex shock
					{
						cashOnHand = cashS[cashInd] - bequestFunHM[tInd][IInd][hsInd][zetaInd][cashInd]; // coh - consumption



																										 //Calculate implied ocnsumption
																										 //Get implied marginal utility (i.e. implied marginal value because there is no price for transforming)

						marginalU = (1 + delta[hsInd]) * pow(Interpolation(&consumFunSM[1][tInd + 1][IInd][hsInd][zetaInd][0], cashS, cashOnHand, CASHDIM), -nu);
						//Invert the bequest function:

						sumH = pow(marginalU / phi1, -(1.0 / nu)) - k1;


						BeqErrorSignHM[tInd][IInd][hsInd][zetaInd][cashInd] = (bequestFunHM[tInd][IInd][hsInd][zetaInd][cashInd] - sumW);///bequestFunHM[tInd][IInd][hsInd][zetaInd][cashInd]; 
						BeqErrorAbsHM[tInd][IInd][hsInd][zetaInd][cashInd] = fabs(BeqErrorSignHM[tInd][IInd][hsInd][zetaInd][cashInd]);

						// WIFE DIES FIRST for (bequestWInd = 0; bequestWInd<BEQUESTDIM; bequestWInd++) 

						// maximization on each node 
						//With bequest defined as a fraction of CashOnHad no need to do the logical check
						cashOnHand = cashS[cashInd] - bequestFunWM[tInd][IInd][hsInd][zetaInd][cashInd];  // coh - consumption

						sumW = (1 + delta[hsInd]) * pow(Interpolation(&consumFunSM[0][tInd + 1][IInd][hsInd][zetaInd][0], cashS, cashOnHand, CASHDIM), -nu);
						//Invert the bequest function:

						sumW = pow(marginalU / phi1, -(1.0 / nu)) - k1;

						BeqErrorSignWM[tInd][IInd][hsInd][zetaInd][cashInd] = (bequestFunWM[tInd][IInd][hsInd][zetaInd][cashInd] - sumW);///bequestFunWM[tInd][IInd][hsInd][zetaInd][cashInd] ;
						BeqErrorAbsWM[tInd][IInd][hsInd][zetaInd][cashInd] = fabs(BeqErrorSignWM[tInd][IInd][hsInd][zetaInd][cashInd]);



					}// end loop through persistent health shock        
				}// end loop through health status    
			}// end loop through permanent income    

		} // end loop for cash on hand 

#if(MPI_COMMENT==1)
		MPI_Allreduce(&BeqErrorSignWM[tInd][0][0][0][0], tempvec2, recsize2, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
		copyit(&BeqErrorSignWM[tInd][0][0][0][0], tempvec2, recsize2);
		MPI_Allreduce(&BeqErrorAbsWM[tInd][0][0][0][0], tempvec2, recsize2, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
		copyit(&BeqErrorAbsWM[tInd][0][0][0][0], tempvec2, recsize2);
		MPI_Allreduce(&BeqErrorSignHM[tInd][0][0][0][0], tempvec2, recsize2, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
		copyit(&BeqErrorSignHM[tInd][0][0][0][0], tempvec2, recsize2);
		MPI_Allreduce(&BeqErrorAbsHM[tInd][0][0][0][0], tempvec2, recsize2, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
		copyit(&BeqErrorAbsHM[tInd][0][0][0][0], tempvec2, recsize2);

#endif     //(MPI_COMMENT==1)

		free(tempvec2);

	}
#endif //Conditional compile on testchecks
	/*--------------------------------------------------------------------------------*/
	/*--------------------------------------------------------------------------------*/

	//---------MARGINAL TAXATION
	//From the formulae we should get t_b *(t_s*y^(t_p -1))*()1+t_s*y^(t_p))^(-1/t_p -1) which is a positive increase in tax
	//Returns the marginal tax rate at y!
	double MargChange2AvgTaxIncomeS(double y)
	{
		double margtax;
		if (y < 0.0)
		{
			// printf("Error! negtive gross income!\n "); 
			return -1;  // this case will be ruled out in maximization  
		}
		else
		{

			margtax = tax_b1 * pow((tax_s1 * pow(y, tax_p1) + 1.0), -1.0 / tax_p1 - 1.0) * (tax_s1 * pow(y, tax_p1 - 1.0));
			if (switchTax == 0) margtax = 0.0;
			return margtax;
		}
	}

	double MargChange2AvgTaxIncomeC(double y)
	{
		double margtax;
		if (y < 0.0)
		{
			// printf("Error! negtive gross income!\n "); 
			return -1;  // this case will be ruled out in maximization  
		}
		else
		{

			margtax = tax_b0 * pow((tax_s0 * pow(y, tax_p0) + 1.0), -1.0 / tax_p0 - 1.0) * (tax_s0 * pow(y, tax_p0 - 1.0));
			if (switchTax == 0) margtax = 0.0;
			return margtax;
		}
	}


	//--------------------------------------------------------------------------------
	//--------------------------------------------------------------------------------
	/*Tax functions based on the Guner et al. estimates (2012)
	*?#?* Added RM 03/2017*/
	double AvgTaxRateIncomeS(double y)
	{
		double tax;
		if (y < 0.0)
		{
			// printf("Error! negtive gross income!\n "); 
			return -1;  // this case will be ruled out in maximization  
		}
		else
		{

			tax = tax_b1 - tax_b1 * pow((tax_s1 * pow(y, tax_p1) + 1.0), -1.0 / tax_p1);
			return tax;
		}
	}

	double AvgTaxRateIncomeC(double y)
	{
		double tax;
		if (y < 0.0)
		{
			// printf("Error! negtive gross income!\n "); 
			return -1;  // this case will be ruled out in maximization  
		}
		else
		{

			tax = tax_b0 - tax_b0 * pow((tax_s0 * pow(y, tax_p0) + 1.0), -1.0 / tax_p0);
			return tax;
		}
	}
